一、扩展接口定义 chrome.bookmarks
使用 chrome.bookmarks
API 创建、整理以及以其他方式操纵书签。另请参阅覆盖网页(可用于创建自定义"书签管理器"页面)。
更多参考chrome.bookmarks | API | Chrome for Developers (google.cn)
扩展可以请从 chrome-extension-samples 安装 bookmarks API 示例 存储库
二、扩展接口c++定义
chrome\common\extensions\api\bookmarks.json
cpp
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[
{
"namespace": "bookmarks",
"description": "Use the <code>chrome.bookmarks</code> API to create, organize, and otherwise manipulate bookmarks. Also see <a href='override'>Override Pages</a>, which you can use to create a custom Bookmark Manager page.",
"properties": {
"MAX_WRITE_OPERATIONS_PER_HOUR": {
"value": 1000000,
"deprecated": "Bookmark write operations are no longer limited by Chrome.",
"description": ""
},
"MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE": {
"value": 1000000,
"deprecated": "Bookmark write operations are no longer limited by Chrome.",
"description": ""
}
},
"types": [
{
"id": "BookmarkTreeNodeUnmodifiable",
"type": "string",
"enum": ["managed"],
"description": "Indicates the reason why this node is unmodifiable. The <var>managed</var> value indicates that this node was configured by the system administrator. Omitted if the node can be modified by the user and the extension (default)."
},
{
"id": "BookmarkTreeNode",
"type": "object",
"description": "A node (either a bookmark or a folder) in the bookmark tree. Child nodes are ordered within their parent folder.",
"properties": {
"id": {
"type": "string",
"minimum": 0,
"description": "The unique identifier for the node. IDs are unique within the current profile, and they remain valid even after the browser is restarted."
},
"parentId": {
"type": "string",
"minimum": 0,
"optional": true,
"description": "The <code>id</code> of the parent folder. Omitted for the root node."
},
"index": {
"type": "integer",
"optional": true,
"description": "The 0-based position of this node within its parent folder."
},
"url": {
"type": "string",
"optional": true,
"description": "The URL navigated to when a user clicks the bookmark. Omitted for folders."
},
"title": {
"type": "string",
"description": "The text displayed for the node."
},
"dateAdded": {
"type": "number",
"optional": true,
"description": "When this node was created, in milliseconds since the epoch (<code>new Date(dateAdded)</code>)."
},
"dateLastUsed": {
"type": "number",
"optional": true,
"description": "When this node was last opened, in milliseconds since the epoch. Not set for folders."
},
"dateGroupModified": {
"type": "number",
"optional": true,
"description": "When the contents of this folder last changed, in milliseconds since the epoch."
},
"unmodifiable": {
"$ref": "BookmarkTreeNodeUnmodifiable",
"optional": true,
"description": "Indicates the reason why this node is unmodifiable. The <var>managed</var> value indicates that this node was configured by the system administrator or by the custodian of a supervised user. Omitted if the node can be modified by the user and the extension (default)."
},
"children": {
"type": "array",
"optional": true,
"items": { "$ref": "BookmarkTreeNode" },
"description": "An ordered list of children of this node."
}
}
},
{
"id": "CreateDetails",
"description": "Object passed to the create() function.",
"inline_doc": true,
"type": "object",
"properties": {
"parentId": {
"type": "string",
"serialized_type": "int64",
"optional": true,
"description": "Defaults to the Other Bookmarks folder."
},
"index": {
"type": "integer",
"minimum": 0,
"optional": true
},
"title": {
"type": "string",
"optional": true
},
"url": {
"type": "string",
"optional": true
}
}
}
],
"functions": [
{
"name": "get",
"type": "function",
"description": "Retrieves the specified BookmarkTreeNode(s).",
"parameters": [
{
"name": "idOrIdList",
"description": "A single string-valued id, or an array of string-valued ids",
"choices": [
{
"type": "string",
"serialized_type": "int64"
},
{
"type": "array",
"items": {
"type": "string",
"serialized_type": "int64"
},
"minItems": 1
}
]
}
],
"returns_async": {
"name": "callback",
"parameters": [
{
"name": "results",
"type": "array",
"items": { "$ref": "BookmarkTreeNode" }
}
]
}
},
{
"name": "getChildren",
"type": "function",
"description": "Retrieves the children of the specified BookmarkTreeNode id.",
"parameters": [
{
"type": "string",
"serialized_type": "int64",
"name": "id"
}
],
"returns_async": {
"name": "callback",
"parameters": [
{
"name": "results",
"type": "array",
"items": { "$ref": "BookmarkTreeNode"}
}
]
}
},
{
"name": "getRecent",
"type": "function",
"description": "Retrieves the recently added bookmarks.",
"parameters": [
{
"type": "integer",
"minimum": 1,
"name": "numberOfItems",
"description": "The maximum number of items to return."
}
],
"returns_async": {
"name": "callback",
"parameters": [
{
"name": "results",
"type": "array",
"items": { "$ref": "BookmarkTreeNode" }
}
]
}
},
{
"name": "getTree",
"type": "function",
"description": "Retrieves the entire Bookmarks hierarchy.",
"parameters": [],
"returns_async": {
"name": "callback",
"parameters": [
{
"name": "results",
"type": "array",
"items": { "$ref": "BookmarkTreeNode" }
}
]
}
},
{
"name": "getSubTree",
"type": "function",
"description": "Retrieves part of the Bookmarks hierarchy, starting at the specified node.",
"parameters": [
{
"type": "string",
"serialized_type": "int64",
"name": "id",
"description": "The ID of the root of the subtree to retrieve."
}
],
"returns_async": {
"name": "callback",
"parameters": [
{
"name": "results",
"type": "array",
"items": { "$ref": "BookmarkTreeNode" }
}
]
}
},
{
"name": "search",
"type": "function",
"description": "Searches for BookmarkTreeNodes matching the given query. Queries specified with an object produce BookmarkTreeNodes matching all specified properties.",
"parameters": [
{
"name": "query",
"description": "Either a string of words and quoted phrases that are matched against bookmark URLs and titles, or an object. If an object, the properties <code>query</code>, <code>url</code>, and <code>title</code> may be specified and bookmarks matching all specified properties will be produced.",
"choices": [
{
"type": "string",
"description": "A string of words and quoted phrases that are matched against bookmark URLs and titles."
},
{
"type": "object",
"description": "An object specifying properties and values to match when searching. Produces bookmarks matching all properties.",
"properties": {
"query": {
"type": "string",
"optional": true,
"description": "A string of words and quoted phrases that are matched against bookmark URLs and titles."
},
"url": {
"type": "string",
"optional": true,
"description": "The URL of the bookmark; matches verbatim. Note that folders have no URL."
},
"title": {
"type": "string",
"optional": true,
"description": "The title of the bookmark; matches verbatim."
}
}
}
]
}
],
"returns_async": {
"name": "callback",
"parameters": [
{
"name": "results",
"type": "array",
"items": { "$ref": "BookmarkTreeNode" }
}
]
}
},
{
"name": "create",
"type": "function",
"description": "Creates a bookmark or folder under the specified parentId. If url is NULL or missing, it will be a folder.",
"parameters": [
{
"$ref": "CreateDetails",
"name": "bookmark"
}
],
"returns_async": {
"name": "callback",
"optional": true,
"parameters": [
{
"name": "result",
"$ref": "BookmarkTreeNode"
}
]
}
},
{
"name": "move",
"type": "function",
"description": "Moves the specified BookmarkTreeNode to the provided location.",
"parameters": [
{
"type": "string",
"serialized_type": "int64",
"name": "id"
},
{
"type": "object",
"name": "destination",
"properties": {
"parentId": {
"type": "string",
"optional": true
},
"index": {
"type": "integer",
"minimum": 0,
"optional": true
}
}
}
],
"returns_async": {
"name": "callback",
"optional": true,
"parameters": [
{
"name": "result",
"$ref": "BookmarkTreeNode"
}
]
}
},
{
"name": "update",
"type": "function",
"description": "Updates the properties of a bookmark or folder. Specify only the properties that you want to change; unspecified properties will be left unchanged. <b>Note:</b> Currently, only 'title' and 'url' are supported.",
"parameters": [
{
"type": "string",
"serialized_type": "int64",
"name": "id"
},
{
"type": "object",
"name": "changes",
"properties": {
"title": {
"type": "string",
"optional": true
},
"url": {
"type": "string",
"optional": true
}
}
}
],
"returns_async": {
"name": "callback",
"optional": true,
"parameters": [
{
"name": "result",
"$ref": "BookmarkTreeNode"
}
]
}
},
{
"name": "remove",
"type": "function",
"description": "Removes a bookmark or an empty bookmark folder.",
"parameters": [
{
"type": "string",
"serialized_type": "int64",
"name": "id"
}
],
"returns_async": {
"name": "callback",
"optional": true,
"parameters": []
}
},
{
"name": "removeTree",
"type": "function",
"description": "Recursively removes a bookmark folder.",
"parameters": [
{
"type": "string",
"serialized_type": "int64",
"name": "id"
}
],
"returns_async": {
"name": "callback",
"optional": true,
"parameters": []
}
}
],
"events": [
{
"name": "onCreated",
"type": "function",
"description": "Fired when a bookmark or folder is created.",
"parameters": [
{
"type": "string",
"name": "id"
},
{
"$ref": "BookmarkTreeNode",
"name": "bookmark"
}
]
},
{
"name": "onRemoved",
"type": "function",
"description": "Fired when a bookmark or folder is removed. When a folder is removed recursively, a single notification is fired for the folder, and none for its contents.",
"parameters": [
{
"type": "string",
"name": "id"
},
{
"type": "object",
"name": "removeInfo",
"properties": {
"parentId": { "type": "string" },
"index": { "type": "integer" },
"node": { "$ref": "BookmarkTreeNode" }
}
}
]
},
{
"name": "onChanged",
"type": "function",
"description": "Fired when a bookmark or folder changes. <b>Note:</b> Currently, only title and url changes trigger this.",
"parameters": [
{
"type": "string",
"name": "id"
},
{
"type": "object",
"name": "changeInfo",
"properties": {
"title": { "type": "string" },
"url": {
"type": "string",
"optional": true
}
}
}
]
},
{
"name": "onMoved",
"type": "function",
"description": "Fired when a bookmark or folder is moved to a different parent folder.",
"parameters": [
{
"type": "string",
"name": "id"
},
{
"type": "object",
"name": "moveInfo",
"properties": {
"parentId": { "type": "string" },
"index": { "type": "integer" },
"oldParentId": { "type": "string" },
"oldIndex": { "type": "integer" }
}
}
]
},
{
"name": "onChildrenReordered",
"type": "function",
"description": "Fired when the children of a folder have changed their order due to the order being sorted in the UI. This is not called as a result of a move().",
"parameters": [
{
"type": "string",
"name": "id"
},
{
"type": "object",
"name": "reorderInfo",
"properties": {
"childIds": {
"type": "array",
"items": { "type": "string" }
}
}
}
]
},
{
"name": "onImportBegan",
"type": "function",
"description": "Fired when a bookmark import session is begun. Expensive observers should ignore onCreated updates until onImportEnded is fired. Observers should still handle other notifications immediately.",
"parameters": []
},
{
"name": "onImportEnded",
"type": "function",
"description": "Fired when a bookmark import session is ended.",
"parameters": []
}
]
}
]
bookmarks.json生成对应文件:
out\Debug\gen\chrome\common\extensions\api\bookmarks.cc
out\Debug\gen\chrome\common\extensions\api\bookmarks.h
三、bookmarks函数实现:
chrome\browser\extensions\api\bookmarks\bookmarks_api.h
chrome\browser\extensions\api\bookmarks\bookmarks_api.cc
cpp
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_API_BOOKMARKS_BOOKMARKS_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_BOOKMARKS_BOOKMARKS_API_H_
#include <stdint.h>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/values.h"
#include "components/bookmarks/browser/base_bookmark_model_observer.h"
#include "components/bookmarks/browser/bookmark_node.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_function.h"
#include "ui/shell_dialogs/select_file_dialog.h"
class Profile;
namespace base {
class FilePath;
}
namespace bookmarks {
class BookmarkModel;
class ManagedBookmarkService;
}
namespace content {
class BrowserContext;
}
namespace extensions {
namespace api {
namespace bookmarks {
struct CreateDetails;
}
}
// Observes BookmarkModel and then routes the notifications as events to
// the extension system.
class BookmarkEventRouter : public bookmarks::BookmarkModelObserver {
public:
explicit BookmarkEventRouter(Profile* profile);
BookmarkEventRouter(const BookmarkEventRouter&) = delete;
BookmarkEventRouter& operator=(const BookmarkEventRouter&) = delete;
~BookmarkEventRouter() override;
// bookmarks::BookmarkModelObserver:
void BookmarkModelLoaded(bookmarks::BookmarkModel* model,
bool ids_reassigned) override;
void BookmarkModelBeingDeleted(bookmarks::BookmarkModel* model) override;
void BookmarkNodeMoved(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* old_parent,
size_t old_index,
const bookmarks::BookmarkNode* new_parent,
size_t new_index) override;
void BookmarkNodeAdded(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* parent,
size_t index,
bool added_by_user) override;
void BookmarkNodeRemoved(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* parent,
size_t old_index,
const bookmarks::BookmarkNode* node,
const std::set<GURL>& removed_urls) override;
void BookmarkAllUserNodesRemoved(bookmarks::BookmarkModel* model,
const std::set<GURL>& removed_urls) override;
void BookmarkNodeChanged(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* node) override;
void BookmarkNodeFaviconChanged(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* node) override;
void BookmarkNodeChildrenReordered(
bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* node) override;
void ExtensiveBookmarkChangesBeginning(
bookmarks::BookmarkModel* model) override;
void ExtensiveBookmarkChangesEnded(bookmarks::BookmarkModel* model) override;
private:
// Helper to actually dispatch an event to extension listeners.
void DispatchEvent(events::HistogramValue histogram_value,
const std::string& event_name,
base::Value::List event_args);
raw_ptr<content::BrowserContext> browser_context_;
raw_ptr<bookmarks::BookmarkModel> model_;
raw_ptr<bookmarks::ManagedBookmarkService> managed_;
};
class BookmarksAPI : public BrowserContextKeyedAPI,
public EventRouter::Observer {
public:
explicit BookmarksAPI(content::BrowserContext* context);
~BookmarksAPI() override;
// KeyedService implementation.
void Shutdown() override;
// BrowserContextKeyedAPI implementation.
static BrowserContextKeyedAPIFactory<BookmarksAPI>* GetFactoryInstance();
// EventRouter::Observer implementation.
void OnListenerAdded(const EventListenerInfo& details) override;
private:
friend class BrowserContextKeyedAPIFactory<BookmarksAPI>;
raw_ptr<content::BrowserContext> browser_context_;
// BrowserContextKeyedAPI implementation.
static const char* service_name() {
return "BookmarksAPI";
}
static const bool kServiceIsNULLWhileTesting = true;
// Created lazily upon OnListenerAdded.
std::unique_ptr<BookmarkEventRouter> bookmark_event_router_;
};
class BookmarksFunction : public ExtensionFunction,
public bookmarks::BaseBookmarkModelObserver {
public:
// ExtensionFunction:
ResponseAction Run() override;
protected:
~BookmarksFunction() override {}
// Run semantic equivalent called when the bookmarks are ready.
// Overrides can return nullptr to further delay responding (a.k.a.
// RespondLater()).
virtual ResponseValue RunOnReady() = 0;
// Helper to get the BookmarkModel.
bookmarks::BookmarkModel* GetBookmarkModel();
// Helper to get the ManagedBookmarkService.
bookmarks::ManagedBookmarkService* GetManagedBookmarkService();
// Helper to get the bookmark node from a given string id.
// If the given id can't be parsed or doesn't refer to a valid node, sets
// |error| and returns nullptr.
const bookmarks::BookmarkNode* GetBookmarkNodeFromId(
const std::string& id_string,
std::string* error);
// Helper to create a bookmark node from a CreateDetails object. If a node
// can't be created based on the given details, sets |error| and returns
// nullptr.
const bookmarks::BookmarkNode* CreateBookmarkNode(
bookmarks::BookmarkModel* model,
const api::bookmarks::CreateDetails& details,
std::string* error);
// Helper that checks if bookmark editing is enabled.
bool EditBookmarksEnabled();
// Helper that checks if |node| can be modified. Returns false if |node|
// is nullptr, or a managed node, or the root node. In these cases the node
// can't be edited, can't have new child nodes appended, and its direct
// children can't be moved or reordered.
bool CanBeModified(const bookmarks::BookmarkNode* node, std::string* error);
Profile* GetProfile();
private:
// bookmarks::BaseBookmarkModelObserver:
void BookmarkModelChanged() override;
void BookmarkModelLoaded(bookmarks::BookmarkModel* model,
bool ids_reassigned) override;
// ExtensionFunction:
void OnResponded() override;
};
class BookmarksGetFunction : public BookmarksFunction {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.get", BOOKMARKS_GET)
protected:
~BookmarksGetFunction() override {}
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
class BookmarksGetChildrenFunction : public BookmarksFunction {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.getChildren", BOOKMARKS_GETCHILDREN)
protected:
~BookmarksGetChildrenFunction() override {}
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
class BookmarksGetRecentFunction : public BookmarksFunction {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.getRecent", BOOKMARKS_GETRECENT)
protected:
~BookmarksGetRecentFunction() override {}
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
class BookmarksGetTreeFunction : public BookmarksFunction {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.getTree", BOOKMARKS_GETTREE)
protected:
~BookmarksGetTreeFunction() override {}
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
class BookmarksGetSubTreeFunction : public BookmarksFunction {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.getSubTree", BOOKMARKS_GETSUBTREE)
protected:
~BookmarksGetSubTreeFunction() override {}
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
class BookmarksSearchFunction : public BookmarksFunction {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.search", BOOKMARKS_SEARCH)
protected:
~BookmarksSearchFunction() override {}
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
class BookmarksRemoveFunctionBase : public BookmarksFunction {
protected:
~BookmarksRemoveFunctionBase() override {}
virtual bool is_recursive() const = 0;
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
class BookmarksRemoveFunction : public BookmarksRemoveFunctionBase {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.remove", BOOKMARKS_REMOVE)
protected:
~BookmarksRemoveFunction() override {}
// BookmarksRemoveFunctionBase:
bool is_recursive() const override;
};
class BookmarksRemoveTreeFunction : public BookmarksRemoveFunctionBase {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.removeTree", BOOKMARKS_REMOVETREE)
protected:
~BookmarksRemoveTreeFunction() override {}
// BookmarksRemoveFunctionBase:
bool is_recursive() const override;
};
class BookmarksCreateFunction : public BookmarksFunction {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.create", BOOKMARKS_CREATE)
protected:
~BookmarksCreateFunction() override {}
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
class BookmarksMoveFunction : public BookmarksFunction {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.move", BOOKMARKS_MOVE)
protected:
~BookmarksMoveFunction() override {}
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
class BookmarksUpdateFunction : public BookmarksFunction {
public:
DECLARE_EXTENSION_FUNCTION("bookmarks.update", BOOKMARKS_UPDATE)
protected:
~BookmarksUpdateFunction() override {}
// BookmarksFunction:
ResponseValue RunOnReady() override;
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_BOOKMARKS_BOOKMARKS_API_H_