Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(861)

Unified Diff: chrome/browser/extensions/extension_bookmarks_module.cc

Issue 8374023: Move bookmarks extension api implementation to bookmarks dir (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix deps, rebase Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/extension_bookmarks_module.cc
diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc
deleted file mode 100644
index 19d23f25ead4b4ff0151e408dbb123636cda0f44..0000000000000000000000000000000000000000
--- a/chrome/browser/extensions/extension_bookmarks_module.cc
+++ /dev/null
@@ -1,943 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/extension_bookmarks_module.h"
-
-#include "base/bind.h"
-#include "base/file_path.h"
-#include "base/i18n/file_util_icu.h"
-#include "base/i18n/time_formatting.h"
-#include "base/json/json_writer.h"
-#include "base/path_service.h"
-#include "base/sha1.h"
-#include "base/stl_util.h"
-#include "base/string16.h"
-#include "base/string_number_conversions.h"
-#include "base/string_util.h"
-#include "base/time.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_codec.h"
-#include "chrome/browser/bookmarks/bookmark_html_writer.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/extensions/extension_bookmark_helpers.h"
-#include "chrome/browser/extensions/extension_bookmarks_module_constants.h"
-#include "chrome/browser/extensions/extension_event_router.h"
-#include "chrome/browser/extensions/extension_function_dispatcher.h"
-#include "chrome/browser/extensions/extensions_quota_service.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/importer/importer_host.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/pref_names.h"
-#include "content/public/browser/notification_service.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace keys = extension_bookmarks_module_constants;
-
-using base::TimeDelta;
-typedef QuotaLimitHeuristic::Bucket Bucket;
-typedef QuotaLimitHeuristic::Config Config;
-typedef QuotaLimitHeuristic::BucketList BucketList;
-typedef ExtensionsQuotaService::TimedLimit TimedLimit;
-typedef ExtensionsQuotaService::SustainedLimit SustainedLimit;
-typedef QuotaLimitHeuristic::BucketMapper BucketMapper;
-
-namespace {
-
-// Generates a default path (including a default filename) that will be
-// used for pre-populating the "Export Bookmarks" file chooser dialog box.
-FilePath GetDefaultFilepathForBookmarkExport() {
- base::Time time = base::Time::Now();
-
- // Concatenate a date stamp to the filename.
-#if defined(OS_POSIX)
- FilePath::StringType filename =
- l10n_util::GetStringFUTF8(IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME,
- base::TimeFormatShortDateNumeric(time));
-#elif defined(OS_WIN)
- FilePath::StringType filename =
- l10n_util::GetStringFUTF16(IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME,
- base::TimeFormatShortDateNumeric(time));
-#endif
-
- file_util::ReplaceIllegalCharactersInPath(&filename, '_');
-
- FilePath default_path;
- PathService::Get(chrome::DIR_USER_DOCUMENTS, &default_path);
- return default_path.Append(filename);
-}
-
-} // namespace
-
-void BookmarksFunction::Run() {
- BookmarkModel* model = profile()->GetBookmarkModel();
- if (!model->IsLoaded()) {
- // Bookmarks are not ready yet. We'll wait.
- registrar_.Add(
- this, chrome::NOTIFICATION_BOOKMARK_MODEL_LOADED,
- content::NotificationService::AllBrowserContextsAndSources());
- AddRef(); // Balanced in Observe().
- return;
- }
-
- bool success = RunImpl();
- if (success) {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_EXTENSION_BOOKMARKS_API_INVOKED,
- content::Source<const Extension>(GetExtension()),
- content::Details<const BookmarksFunction>(this));
- }
- SendResponse(success);
-}
-
-bool BookmarksFunction::GetBookmarkIdAsInt64(
- const std::string& id_string, int64* id) {
- if (base::StringToInt64(id_string, id))
- return true;
-
- error_ = keys::kInvalidIdError;
- return false;
-}
-
-bool BookmarksFunction::EditBookmarksEnabled() {
- if (profile_->GetPrefs()->GetBoolean(prefs::kEditBookmarksEnabled))
- return true;
- error_ = keys::kEditBookmarksDisabled;
- return false;
-}
-
-void BookmarksFunction::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK(type == chrome::NOTIFICATION_BOOKMARK_MODEL_LOADED);
- Profile* source_profile = content::Source<Profile>(source).ptr();
- if (!source_profile || !source_profile->IsSameProfile(profile()))
- return;
-
- DCHECK(profile()->GetBookmarkModel()->IsLoaded());
- Run();
- Release(); // Balanced in Run().
-}
-
-ExtensionBookmarkEventRouter::ExtensionBookmarkEventRouter(
- BookmarkModel* model) : model_(model) {
-}
-
-ExtensionBookmarkEventRouter::~ExtensionBookmarkEventRouter() {
- if (model_) {
- model_->RemoveObserver(this);
- }
-}
-
-void ExtensionBookmarkEventRouter::Init() {
- model_->AddObserver(this);
-}
-
-void ExtensionBookmarkEventRouter::DispatchEvent(Profile *profile,
- const char* event_name,
- const std::string& json_args) {
- if (profile->GetExtensionEventRouter()) {
- profile->GetExtensionEventRouter()->DispatchEventToRenderers(
- event_name, json_args, NULL, GURL());
- }
-}
-
-void ExtensionBookmarkEventRouter::Loaded(BookmarkModel* model,
- bool ids_reassigned) {
- // TODO(erikkay): Perhaps we should send this event down to the extension
- // so they know when it's safe to use the API?
-}
-
-void ExtensionBookmarkEventRouter::BookmarkModelBeingDeleted(
- BookmarkModel* model) {
- model_ = NULL;
-}
-
-void ExtensionBookmarkEventRouter::BookmarkNodeMoved(
- BookmarkModel* model,
- const BookmarkNode* old_parent,
- int old_index,
- const BookmarkNode* new_parent,
- int new_index) {
- ListValue args;
- const BookmarkNode* node = new_parent->GetChild(new_index);
- args.Append(new StringValue(base::Int64ToString(node->id())));
- DictionaryValue* object_args = new DictionaryValue();
- object_args->SetString(keys::kParentIdKey,
- base::Int64ToString(new_parent->id()));
- object_args->SetInteger(keys::kIndexKey, new_index);
- object_args->SetString(keys::kOldParentIdKey,
- base::Int64ToString(old_parent->id()));
- object_args->SetInteger(keys::kOldIndexKey, old_index);
- args.Append(object_args);
-
- std::string json_args;
- base::JSONWriter::Write(&args, false, &json_args);
- DispatchEvent(model->profile(), keys::kOnBookmarkMoved, json_args);
-}
-
-void ExtensionBookmarkEventRouter::BookmarkNodeAdded(BookmarkModel* model,
- const BookmarkNode* parent,
- int index) {
- ListValue args;
- const BookmarkNode* node = parent->GetChild(index);
- args.Append(new StringValue(base::Int64ToString(node->id())));
- DictionaryValue* obj =
- extension_bookmark_helpers::GetNodeDictionary(node, false, false);
- args.Append(obj);
-
- std::string json_args;
- base::JSONWriter::Write(&args, false, &json_args);
- DispatchEvent(model->profile(), keys::kOnBookmarkCreated, json_args);
-}
-
-void ExtensionBookmarkEventRouter::BookmarkNodeRemoved(
- BookmarkModel* model,
- const BookmarkNode* parent,
- int index,
- const BookmarkNode* node) {
- ListValue args;
- args.Append(new StringValue(base::Int64ToString(node->id())));
- DictionaryValue* object_args = new DictionaryValue();
- object_args->SetString(keys::kParentIdKey,
- base::Int64ToString(parent->id()));
- object_args->SetInteger(keys::kIndexKey, index);
- args.Append(object_args);
-
- std::string json_args;
- base::JSONWriter::Write(&args, false, &json_args);
- DispatchEvent(model->profile(), keys::kOnBookmarkRemoved, json_args);
-}
-
-void ExtensionBookmarkEventRouter::BookmarkNodeChanged(
- BookmarkModel* model, const BookmarkNode* node) {
- ListValue args;
- args.Append(new StringValue(base::Int64ToString(node->id())));
-
- // TODO(erikkay) The only three things that BookmarkModel sends this
- // notification for are title, url and favicon. Since we're currently
- // ignoring favicon and since the notification doesn't say which one anyway,
- // for now we only include title and url. The ideal thing would be to change
- // BookmarkModel to indicate what changed.
- DictionaryValue* object_args = new DictionaryValue();
- object_args->SetString(keys::kTitleKey, node->GetTitle());
- if (node->is_url())
- object_args->SetString(keys::kUrlKey, node->url().spec());
- args.Append(object_args);
-
- std::string json_args;
- base::JSONWriter::Write(&args, false, &json_args);
- DispatchEvent(model->profile(), keys::kOnBookmarkChanged, json_args);
-}
-
-void ExtensionBookmarkEventRouter::BookmarkNodeFaviconChanged(
- BookmarkModel* model, const BookmarkNode* node) {
- // TODO(erikkay) anything we should do here?
-}
-
-void ExtensionBookmarkEventRouter::BookmarkNodeChildrenReordered(
- BookmarkModel* model, const BookmarkNode* node) {
- ListValue args;
- args.Append(new StringValue(base::Int64ToString(node->id())));
- int childCount = node->child_count();
- ListValue* children = new ListValue();
- for (int i = 0; i < childCount; ++i) {
- const BookmarkNode* child = node->GetChild(i);
- Value* child_id = new StringValue(base::Int64ToString(child->id()));
- children->Append(child_id);
- }
- DictionaryValue* reorder_info = new DictionaryValue();
- reorder_info->Set(keys::kChildIdsKey, children);
- args.Append(reorder_info);
-
- std::string json_args;
- base::JSONWriter::Write(&args, false, &json_args);
- DispatchEvent(model->profile(),
- keys::kOnBookmarkChildrenReordered,
- json_args);
-}
-
-void ExtensionBookmarkEventRouter::
- BookmarkImportBeginning(BookmarkModel* model) {
- ListValue args;
- std::string json_args;
- base::JSONWriter::Write(&args, false, &json_args);
- DispatchEvent(model->profile(),
- keys::kOnBookmarkImportBegan,
- json_args);
-}
-
-void ExtensionBookmarkEventRouter::BookmarkImportEnding(BookmarkModel* model) {
- ListValue args;
- std::string json_args;
- base::JSONWriter::Write(&args, false, &json_args);
- DispatchEvent(model->profile(),
- keys::kOnBookmarkImportEnded,
- json_args);
-}
-
-bool GetBookmarksFunction::RunImpl() {
- BookmarkModel* model = profile()->GetBookmarkModel();
- scoped_ptr<ListValue> json(new ListValue());
- Value* arg0;
- EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &arg0));
- if (arg0->IsType(Value::TYPE_LIST)) {
- const ListValue* ids = static_cast<const ListValue*>(arg0);
- size_t count = ids->GetSize();
- EXTENSION_FUNCTION_VALIDATE(count > 0);
- for (size_t i = 0; i < count; ++i) {
- int64 id;
- std::string id_string;
- EXTENSION_FUNCTION_VALIDATE(ids->GetString(i, &id_string));
- if (!GetBookmarkIdAsInt64(id_string, &id))
- return false;
- const BookmarkNode* node = model->GetNodeByID(id);
- if (!node) {
- error_ = keys::kNoNodeError;
- return false;
- } else {
- extension_bookmark_helpers::AddNode(node, json.get(), false);
- }
- }
- } else {
- int64 id;
- std::string id_string;
- EXTENSION_FUNCTION_VALIDATE(arg0->GetAsString(&id_string));
- if (!GetBookmarkIdAsInt64(id_string, &id))
- return false;
- const BookmarkNode* node = model->GetNodeByID(id);
- if (!node) {
- error_ = keys::kNoNodeError;
- return false;
- }
- extension_bookmark_helpers::AddNode(node, json.get(), false);
- }
-
- result_.reset(json.release());
- return true;
-}
-
-bool GetBookmarkChildrenFunction::RunImpl() {
- BookmarkModel* model = profile()->GetBookmarkModel();
- int64 id;
- std::string id_string;
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id_string));
- if (!GetBookmarkIdAsInt64(id_string, &id))
- return false;
- scoped_ptr<ListValue> json(new ListValue());
- const BookmarkNode* node = model->GetNodeByID(id);
- if (!node) {
- error_ = keys::kNoNodeError;
- return false;
- }
- int child_count = node->child_count();
- for (int i = 0; i < child_count; ++i) {
- const BookmarkNode* child = node->GetChild(i);
- extension_bookmark_helpers::AddNode(child, json.get(), false);
- }
-
- result_.reset(json.release());
- return true;
-}
-
-bool GetBookmarkRecentFunction::RunImpl() {
- int number_of_items;
- EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &number_of_items));
- if (number_of_items < 1)
- return false;
-
- BookmarkModel* model = profile()->GetBookmarkModel();
- ListValue* json = new ListValue();
- std::vector<const BookmarkNode*> nodes;
- bookmark_utils::GetMostRecentlyAddedEntries(model, number_of_items, &nodes);
- std::vector<const BookmarkNode*>::iterator i = nodes.begin();
- for (; i != nodes.end(); ++i) {
- const BookmarkNode* node = *i;
- extension_bookmark_helpers::AddNode(node, json, false);
- }
- result_.reset(json);
- return true;
-}
-
-bool GetBookmarkTreeFunction::RunImpl() {
- BookmarkModel* model = profile()->GetBookmarkModel();
- scoped_ptr<ListValue> json(new ListValue());
- const BookmarkNode* node = model->root_node();
- extension_bookmark_helpers::AddNode(node, json.get(), true);
- result_.reset(json.release());
- return true;
-}
-
-bool GetBookmarkSubTreeFunction::RunImpl() {
- BookmarkModel* model = profile()->GetBookmarkModel();
- scoped_ptr<ListValue> json(new ListValue());
- Value* arg0;
- EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &arg0));
- int64 id;
- std::string id_string;
- EXTENSION_FUNCTION_VALIDATE(arg0->GetAsString(&id_string));
- if (!GetBookmarkIdAsInt64(id_string, &id))
- return false;
- const BookmarkNode* node = model->GetNodeByID(id);
- if (!node) {
- error_ = keys::kNoNodeError;
- return false;
- }
- extension_bookmark_helpers::AddNode(node, json.get(), true);
- result_.reset(json.release());
- return true;
-}
-
-bool SearchBookmarksFunction::RunImpl() {
- string16 query;
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &query));
-
- BookmarkModel* model = profile()->GetBookmarkModel();
- ListValue* json = new ListValue();
- std::string lang = profile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
- std::vector<const BookmarkNode*> nodes;
- bookmark_utils::GetBookmarksContainingText(model, query,
- std::numeric_limits<int>::max(),
- lang, &nodes);
- std::vector<const BookmarkNode*>::iterator i = nodes.begin();
- for (; i != nodes.end(); ++i) {
- const BookmarkNode* node = *i;
- extension_bookmark_helpers::AddNode(node, json, false);
- }
-
- result_.reset(json);
- return true;
-}
-
-// static
-bool RemoveBookmarkFunction::ExtractIds(const ListValue* args,
- std::list<int64>* ids,
- bool* invalid_id) {
- std::string id_string;
- if (!args->GetString(0, &id_string))
- return false;
- int64 id;
- if (base::StringToInt64(id_string, &id))
- ids->push_back(id);
- else
- *invalid_id = true;
- return true;
-}
-
-bool RemoveBookmarkFunction::RunImpl() {
- if (!EditBookmarksEnabled())
- return false;
- std::list<int64> ids;
- bool invalid_id = false;
- EXTENSION_FUNCTION_VALIDATE(ExtractIds(args_.get(), &ids, &invalid_id));
- if (invalid_id) {
- error_ = keys::kInvalidIdError;
- return false;
- }
- bool recursive = false;
- if (name() == RemoveTreeBookmarkFunction::function_name())
- recursive = true;
-
- BookmarkModel* model = profile()->GetBookmarkModel();
- size_t count = ids.size();
- EXTENSION_FUNCTION_VALIDATE(count > 0);
- for (std::list<int64>::iterator it = ids.begin(); it != ids.end(); ++it) {
- if (!extension_bookmark_helpers::RemoveNode(model, *it, recursive, &error_))
- return false;
- }
- return true;
-}
-
-bool CreateBookmarkFunction::RunImpl() {
- if (!EditBookmarksEnabled())
- return false;
- DictionaryValue* json;
- EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
- EXTENSION_FUNCTION_VALIDATE(json != NULL);
-
- BookmarkModel* model = profile()->GetBookmarkModel();
- int64 parentId;
- if (!json->HasKey(keys::kParentIdKey)) {
- // Optional, default to "other bookmarks".
- parentId = model->other_node()->id();
- } else {
- std::string parentId_string;
- EXTENSION_FUNCTION_VALIDATE(json->GetString(keys::kParentIdKey,
- &parentId_string));
- if (!GetBookmarkIdAsInt64(parentId_string, &parentId))
- return false;
- }
- const BookmarkNode* parent = model->GetNodeByID(parentId);
- if (!parent) {
- error_ = keys::kNoParentError;
- return false;
- }
- if (parent->is_root()) { // Can't create children of the root.
- error_ = keys::kModifySpecialError;
- return false;
- }
-
- int index;
- if (!json->HasKey(keys::kIndexKey)) { // Optional (defaults to end).
- index = parent->child_count();
- } else {
- EXTENSION_FUNCTION_VALIDATE(json->GetInteger(keys::kIndexKey, &index));
- if (index > parent->child_count() || index < 0) {
- error_ = keys::kInvalidIndexError;
- return false;
- }
- }
-
- string16 title;
- json->GetString(keys::kTitleKey, &title); // Optional.
- std::string url_string;
- json->GetString(keys::kUrlKey, &url_string); // Optional.
- GURL url(url_string);
- if (!url.is_empty() && !url.is_valid()) {
- error_ = keys::kInvalidUrlError;
- return false;
- }
-
- const BookmarkNode* node;
- if (url_string.length())
- node = model->AddURL(parent, index, title, url);
- else
- node = model->AddFolder(parent, index, title);
- DCHECK(node);
- if (!node) {
- error_ = keys::kNoNodeError;
- return false;
- }
-
- DictionaryValue* ret =
- extension_bookmark_helpers::GetNodeDictionary(node, false, false);
- result_.reset(ret);
-
- return true;
-}
-
-// static
-bool MoveBookmarkFunction::ExtractIds(const ListValue* args,
- std::list<int64>* ids,
- bool* invalid_id) {
- // For now, Move accepts ID parameters in the same way as an Update.
- return UpdateBookmarkFunction::ExtractIds(args, ids, invalid_id);
-}
-
-bool MoveBookmarkFunction::RunImpl() {
- if (!EditBookmarksEnabled())
- return false;
- std::list<int64> ids;
- bool invalid_id = false;
- EXTENSION_FUNCTION_VALIDATE(ExtractIds(args_.get(), &ids, &invalid_id));
- if (invalid_id) {
- error_ = keys::kInvalidIdError;
- return false;
- }
- EXTENSION_FUNCTION_VALIDATE(ids.size() == 1);
-
- DictionaryValue* destination;
- EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &destination));
-
- BookmarkModel* model = profile()->GetBookmarkModel();
- const BookmarkNode* node = model->GetNodeByID(ids.front());
- if (!node) {
- error_ = keys::kNoNodeError;
- return false;
- }
- if (model->is_permanent_node(node)) {
- error_ = keys::kModifySpecialError;
- return false;
- }
-
- const BookmarkNode* parent = NULL;
- if (!destination->HasKey(keys::kParentIdKey)) {
- // Optional, defaults to current parent.
- parent = node->parent();
- } else {
- std::string parentId_string;
- EXTENSION_FUNCTION_VALIDATE(destination->GetString(keys::kParentIdKey,
- &parentId_string));
- int64 parentId;
- if (!GetBookmarkIdAsInt64(parentId_string, &parentId))
- return false;
-
- parent = model->GetNodeByID(parentId);
- }
- if (!parent) {
- error_ = keys::kNoParentError;
- // TODO(erikkay) return an error message.
- return false;
- }
- if (parent == model->root_node()) {
- error_ = keys::kModifySpecialError;
- return false;
- }
-
- int index;
- if (destination->HasKey(keys::kIndexKey)) { // Optional (defaults to end).
- EXTENSION_FUNCTION_VALIDATE(destination->GetInteger(keys::kIndexKey,
- &index));
- if (index > parent->child_count() || index < 0) {
- error_ = keys::kInvalidIndexError;
- return false;
- }
- } else {
- index = parent->child_count();
- }
-
- model->Move(node, parent, index);
-
- DictionaryValue* ret =
- extension_bookmark_helpers::GetNodeDictionary(node, false, false);
- result_.reset(ret);
-
- return true;
-}
-
-// static
-bool UpdateBookmarkFunction::ExtractIds(const ListValue* args,
- std::list<int64>* ids,
- bool* invalid_id) {
- // For now, Update accepts ID parameters in the same way as an Remove.
- return RemoveBookmarkFunction::ExtractIds(args, ids, invalid_id);
-}
-
-bool UpdateBookmarkFunction::RunImpl() {
- if (!EditBookmarksEnabled())
- return false;
- std::list<int64> ids;
- bool invalid_id = false;
- EXTENSION_FUNCTION_VALIDATE(ExtractIds(args_.get(), &ids, &invalid_id));
- if (invalid_id) {
- error_ = keys::kInvalidIdError;
- return false;
- }
- EXTENSION_FUNCTION_VALIDATE(ids.size() == 1);
-
- DictionaryValue* updates;
- EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &updates));
-
- // Optional but we need to distinguish non present from an empty title.
- string16 title;
- const bool has_title = updates->GetString(keys::kTitleKey, &title);
-
- // Optional.
- std::string url_string;
- updates->GetString(keys::kUrlKey, &url_string);
- GURL url(url_string);
- if (!url_string.empty() && !url.is_valid()) {
- error_ = keys::kInvalidUrlError;
- return false;
- }
-
- BookmarkModel* model = profile()->GetBookmarkModel();
- const BookmarkNode* node = model->GetNodeByID(ids.front());
- if (!node) {
- error_ = keys::kNoNodeError;
- return false;
- }
- if (model->is_permanent_node(node)) {
- error_ = keys::kModifySpecialError;
- return false;
- }
- if (has_title)
- model->SetTitle(node, title);
- if (!url.is_empty())
- model->SetURL(node, url);
-
- DictionaryValue* ret =
- extension_bookmark_helpers::GetNodeDictionary(node, false, false);
- result_.reset(ret);
-
- return true;
-}
-
-// Mapper superclass for BookmarkFunctions.
-template <typename BucketIdType>
-class BookmarkBucketMapper : public BucketMapper {
- public:
- virtual ~BookmarkBucketMapper() { STLDeleteValues(&buckets_); }
- protected:
- Bucket* GetBucket(const BucketIdType& id) {
- Bucket* b = buckets_[id];
- if (b == NULL) {
- b = new Bucket();
- buckets_[id] = b;
- }
- return b;
- }
- private:
- std::map<BucketIdType, Bucket*> buckets_;
-};
-
-// Mapper for 'bookmarks.create'. Maps "same input to bookmarks.create" to a
-// unique bucket.
-class CreateBookmarkBucketMapper : public BookmarkBucketMapper<std::string> {
- public:
- explicit CreateBookmarkBucketMapper(Profile* profile) : profile_(profile) {}
- // TODO(tim): This should share code with CreateBookmarkFunction::RunImpl,
- // but I can't figure out a good way to do that with all the macros.
- virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {
- DictionaryValue* json;
- if (!args->GetDictionary(0, &json))
- return;
-
- std::string parent_id;
- if (json->HasKey(keys::kParentIdKey)) {
- if (!json->GetString(keys::kParentIdKey, &parent_id))
- return;
- }
- BookmarkModel* model = profile_->GetBookmarkModel();
-
- int64 parent_id_int64;
- base::StringToInt64(parent_id, &parent_id_int64);
- const BookmarkNode* parent = model->GetNodeByID(parent_id_int64);
- if (!parent)
- return;
-
- std::string bucket_id = UTF16ToUTF8(parent->GetTitle());
- std::string title;
- json->GetString(keys::kTitleKey, &title);
- std::string url_string;
- json->GetString(keys::kUrlKey, &url_string);
-
- bucket_id += title;
- bucket_id += url_string;
- // 20 bytes (SHA1 hash length) is very likely less than most of the
- // |bucket_id| strings we construct here, so we hash it to save space.
- buckets->push_back(GetBucket(base::SHA1HashString(bucket_id)));
- }
- private:
- Profile* profile_;
-};
-
-// Mapper for 'bookmarks.remove'.
-class RemoveBookmarksBucketMapper : public BookmarkBucketMapper<std::string> {
- public:
- explicit RemoveBookmarksBucketMapper(Profile* profile) : profile_(profile) {}
- virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {
- typedef std::list<int64> IdList;
- IdList ids;
- bool invalid_id = false;
- if (!RemoveBookmarkFunction::ExtractIds(args, &ids, &invalid_id) ||
- invalid_id) {
- return;
- }
-
- for (IdList::iterator it = ids.begin(); it != ids.end(); ++it) {
- BookmarkModel* model = profile_->GetBookmarkModel();
- const BookmarkNode* node = model->GetNodeByID(*it);
- if (!node || node->is_root())
- return;
-
- std::string bucket_id;
- bucket_id += UTF16ToUTF8(node->parent()->GetTitle());
- bucket_id += UTF16ToUTF8(node->GetTitle());
- bucket_id += node->url().spec();
- buckets->push_back(GetBucket(base::SHA1HashString(bucket_id)));
- }
- }
- private:
- Profile* profile_;
-};
-
-// Mapper for any bookmark function accepting bookmark IDs as parameters, where
-// a distinct ID corresponds to a single item in terms of quota limiting. This
-// is inappropriate for bookmarks.remove, for example, since repeated removals
-// of the same item will actually have a different ID each time.
-template <class FunctionType>
-class BookmarkIdMapper : public BookmarkBucketMapper<int64> {
- public:
- typedef std::list<int64> IdList;
- virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {
- IdList ids;
- bool invalid_id = false;
- if (!FunctionType::ExtractIds(args, &ids, &invalid_id) || invalid_id)
- return;
- for (IdList::iterator it = ids.begin(); it != ids.end(); ++it)
- buckets->push_back(GetBucket(*it));
- }
-};
-
-// Builds heuristics for all BookmarkFunctions using specialized BucketMappers.
-class BookmarksQuotaLimitFactory {
- public:
- // For id-based bookmark functions.
- template <class FunctionType>
- static void Build(QuotaLimitHeuristics* heuristics) {
- BuildWithMappers(heuristics, new BookmarkIdMapper<FunctionType>(),
- new BookmarkIdMapper<FunctionType>());
- }
-
- // For bookmarks.create.
- static void BuildForCreate(QuotaLimitHeuristics* heuristics,
- Profile* profile) {
- BuildWithMappers(heuristics, new CreateBookmarkBucketMapper(profile),
- new CreateBookmarkBucketMapper(profile));
- }
-
- // For bookmarks.remove.
- static void BuildForRemove(QuotaLimitHeuristics* heuristics,
- Profile* profile) {
- BuildWithMappers(heuristics, new RemoveBookmarksBucketMapper(profile),
- new RemoveBookmarksBucketMapper(profile));
- }
-
- private:
- static void BuildWithMappers(QuotaLimitHeuristics* heuristics,
- BucketMapper* short_mapper, BucketMapper* long_mapper) {
- TimedLimit* timed = new TimedLimit(kLongLimitConfig, long_mapper);
- // A max of two operations per minute, sustained over 10 minutes.
- SustainedLimit* sustained = new SustainedLimit(TimeDelta::FromMinutes(10),
- kShortLimitConfig, short_mapper);
- heuristics->push_back(timed);
- heuristics->push_back(sustained);
- }
-
- // The quota configurations used for all BookmarkFunctions.
- static const Config kShortLimitConfig;
- static const Config kLongLimitConfig;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(BookmarksQuotaLimitFactory);
-};
-
-const Config BookmarksQuotaLimitFactory::kShortLimitConfig = {
- 2, // 2 tokens per interval.
- TimeDelta::FromMinutes(1) // 1 minute long refill interval.
-};
-
-const Config BookmarksQuotaLimitFactory::kLongLimitConfig = {
- 100, // 100 tokens per interval.
- TimeDelta::FromHours(1) // 1 hour long refill interval.
-};
-
-// And finally, building the individual heuristics for each function.
-void RemoveBookmarkFunction::GetQuotaLimitHeuristics(
- QuotaLimitHeuristics* heuristics) const {
- BookmarksQuotaLimitFactory::BuildForRemove(heuristics, profile());
-}
-
-void MoveBookmarkFunction::GetQuotaLimitHeuristics(
- QuotaLimitHeuristics* heuristics) const {
- BookmarksQuotaLimitFactory::Build<MoveBookmarkFunction>(heuristics);
-}
-
-void UpdateBookmarkFunction::GetQuotaLimitHeuristics(
- QuotaLimitHeuristics* heuristics) const {
- BookmarksQuotaLimitFactory::Build<UpdateBookmarkFunction>(heuristics);
-};
-
-void CreateBookmarkFunction::GetQuotaLimitHeuristics(
- QuotaLimitHeuristics* heuristics) const {
- BookmarksQuotaLimitFactory::BuildForCreate(heuristics, profile());
-}
-
-BookmarksIOFunction::BookmarksIOFunction() {}
-
-BookmarksIOFunction::~BookmarksIOFunction() {
- // There may be pending file dialogs, we need to tell them that we've gone
- // away so they don't try and call back to us.
- if (select_file_dialog_.get())
- select_file_dialog_->ListenerDestroyed();
-}
-
-void BookmarksIOFunction::SelectFile(SelectFileDialog::Type type) {
- // GetDefaultFilepathForBookmarkExport() might have to touch the filesystem
- // (stat or access, for example), so this requires a thread with IO allowed.
- if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&BookmarksIOFunction::SelectFile, this, type));
- return;
- }
-
- // Pre-populating the filename field in case this is a SELECT_SAVEAS_FILE
- // dialog. If not, there is no filename field in the dialog box.
- FilePath default_path;
- if (type == SelectFileDialog::SELECT_SAVEAS_FILE)
- default_path = GetDefaultFilepathForBookmarkExport();
- else
- DCHECK(type == SelectFileDialog::SELECT_OPEN_FILE);
-
- // After getting the |default_path|, ask the UI to display the file dialog.
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&BookmarksIOFunction::ShowSelectFileDialog, this,
- type, default_path));
-}
-
-void BookmarksIOFunction::ShowSelectFileDialog(SelectFileDialog::Type type,
- FilePath default_path) {
- // Balanced in one of the three callbacks of SelectFileDialog:
- // either FileSelectionCanceled, MultiFilesSelected, or FileSelected
- AddRef();
- select_file_dialog_ = SelectFileDialog::Create(this);
- SelectFileDialog::FileTypeInfo file_type_info;
- file_type_info.extensions.resize(1);
- file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
-
- TabContents* tab_contents = dispatcher()->delegate()->
- GetAssociatedTabContents();
-
- // |tab_contents| can be NULL (for background pages), which is fine. In such
- // a case if file-selection dialogs are forbidden by policy, we will not
- // show an InfoBar, which is better than letting one appear out of the blue.
- select_file_dialog_->SelectFile(type,
- string16(),
- default_path,
- &file_type_info,
- 0,
- FILE_PATH_LITERAL(""),
- tab_contents,
- NULL,
- NULL);
-}
-
-void BookmarksIOFunction::FileSelectionCanceled(void* params) {
- Release(); // Balanced in BookmarksIOFunction::SelectFile()
-}
-
-void BookmarksIOFunction::MultiFilesSelected(
- const std::vector<FilePath>& files, void* params) {
- Release(); // Balanced in BookmarsIOFunction::SelectFile()
- NOTREACHED() << "Should not be able to select multiple files";
-}
-
-bool ImportBookmarksFunction::RunImpl() {
- if (!EditBookmarksEnabled())
- return false;
- SelectFile(SelectFileDialog::SELECT_OPEN_FILE);
- return true;
-}
-
-void ImportBookmarksFunction::FileSelected(const FilePath& path,
- int index,
- void* params) {
- scoped_refptr<ImporterHost> importer_host(new ImporterHost);
- importer::SourceProfile source_profile;
- source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE;
- source_profile.source_path = path;
- importer_host->StartImportSettings(source_profile,
- profile(),
- importer::FAVORITES,
- new ProfileWriter(profile()),
- true);
- Release(); // Balanced in BookmarksIOFunction::SelectFile()
-}
-
-bool ExportBookmarksFunction::RunImpl() {
- SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE);
- return true;
-}
-
-void ExportBookmarksFunction::FileSelected(const FilePath& path,
- int index,
- void* params) {
- bookmark_html_writer::WriteBookmarks(profile(), path, NULL);
- Release(); // Balanced in BookmarksIOFunction::SelectFile()
-}

Powered by Google App Engine
This is Rietveld 408576698