OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_bookmarks_module.h" | 5 #include "chrome/browser/extensions/extension_bookmarks_module.h" |
6 | 6 |
| 7 #include "base/json_writer.h" |
7 #include "chrome/browser/bookmarks/bookmark_codec.h" | 8 #include "chrome/browser/bookmarks/bookmark_codec.h" |
8 #include "chrome/browser/bookmarks/bookmark_model.h" | 9 #include "chrome/browser/bookmarks/bookmark_model.h" |
9 #include "chrome/browser/bookmarks/bookmark_utils.h" | 10 #include "chrome/browser/bookmarks/bookmark_utils.h" |
| 11 #include "chrome/browser/browser_list.h" |
| 12 #include "chrome/browser/extensions/extension_message_service.h" |
10 #include "chrome/browser/profile.h" | 13 #include "chrome/browser/profile.h" |
11 | 14 |
12 namespace { | 15 namespace { |
13 // keys | 16 // keys |
14 const wchar_t* kIdKey = L"id"; | 17 const wchar_t* kIdKey = L"id"; |
15 const wchar_t* kIndexKey = L"index"; | 18 const wchar_t* kIndexKey = L"index"; |
16 const wchar_t* kParentIdKey = L"parentId"; | 19 const wchar_t* kParentIdKey = L"parentId"; |
| 20 const wchar_t* kOldIndexKey = L"oldIndex"; |
| 21 const wchar_t* kOldParentIdKey = L"oldParentId"; |
17 const wchar_t* kUrlKey = L"url"; | 22 const wchar_t* kUrlKey = L"url"; |
18 const wchar_t* kTitleKey = L"title"; | 23 const wchar_t* kTitleKey = L"title"; |
19 const wchar_t* kChildrenIdsKey = L"childrenIds"; | 24 const wchar_t* kChildrenIdsKey = L"childrenIds"; |
20 const wchar_t* kChildrenKey = L"childrenIds"; | 25 const wchar_t* kChildrenKey = L"childrenIds"; |
21 const wchar_t* kRecursiveKey = L"recursive"; | 26 const wchar_t* kRecursiveKey = L"recursive"; |
22 | 27 |
23 // errors | 28 // errors |
24 const char* kNoNodeError = "Can't find bookmark for id."; | 29 const char* kNoNodeError = "Can't find bookmark for id."; |
25 const char* kNoParentError = "Can't find parent bookmark for id."; | 30 const char* kNoParentError = "Can't find parent bookmark for id."; |
26 const char* kFolderNotEmptyError = | 31 const char* kFolderNotEmptyError = |
27 "Can't remove non-empty folder (use recursive to force)."; | 32 "Can't remove non-empty folder (use recursive to force)."; |
28 const char* kInvalidIndexError = "Index out of bounds."; | 33 const char* kInvalidIndexError = "Index out of bounds."; |
29 const char* kInvalidUrlError = "Invalid URL."; | 34 const char* kInvalidUrlError = "Invalid URL."; |
30 const char* kModifySpecialError = "Can't modify the root bookmark folders."; | 35 const char* kModifySpecialError = "Can't modify the root bookmark folders."; |
| 36 |
| 37 // events |
| 38 const char* kOnBookmarkAdded = "bookmark-added"; |
| 39 const char* kOnBookmarkRemoved = "bookmark-removed"; |
| 40 const char* kOnBookmarkChanged = "bookmark-changed"; |
| 41 const char* kOnBookmarkMoved = "bookmark-moved"; |
| 42 const char* kOnBookmarkChildrenReordered = "bookmark-children-reordered"; |
31 }; | 43 }; |
32 | 44 |
33 // Helper functions. | 45 // Helper functions. |
34 class ExtensionBookmarks { | 46 class ExtensionBookmarks { |
35 public: | 47 public: |
36 // Convert |node| into a JSON value | 48 // Convert |node| into a JSON value |
37 static DictionaryValue* GetNodeDictionary(BookmarkNode* node, bool recurse) { | 49 static DictionaryValue* GetNodeDictionary(BookmarkNode* node, bool recurse) { |
38 DictionaryValue* dict = new DictionaryValue(); | 50 DictionaryValue* dict = new DictionaryValue(); |
39 dict->SetInteger(kIdKey, node->id()); | 51 dict->SetInteger(kIdKey, node->id()); |
40 | 52 |
(...skipping 28 matching lines...) Loading... |
69 // Add a JSON representation of |node| to the JSON |list|. | 81 // Add a JSON representation of |node| to the JSON |list|. |
70 static void AddNode(BookmarkNode* node, ListValue* list, bool recurse) { | 82 static void AddNode(BookmarkNode* node, ListValue* list, bool recurse) { |
71 DictionaryValue* dict = GetNodeDictionary(node, recurse); | 83 DictionaryValue* dict = GetNodeDictionary(node, recurse); |
72 list->Append(dict); | 84 list->Append(dict); |
73 } | 85 } |
74 | 86 |
75 private: | 87 private: |
76 ExtensionBookmarks(); | 88 ExtensionBookmarks(); |
77 }; | 89 }; |
78 | 90 |
79 // TODO(erikkay): add a recursive version | 91 void BookmarksFunction::Run() { |
| 92 // TODO(erikkay) temporary hack until adding an event listener can notify the |
| 93 // browser. |
| 94 ExtensionBookmarkEventRouter* event_router = |
| 95 ExtensionBookmarkEventRouter::GetSingleton(); |
| 96 BookmarkModel* model = profile()->GetBookmarkModel(); |
| 97 event_router->Observe(model); |
| 98 SyncExtensionFunction::Run(); |
| 99 } |
| 100 |
| 101 // static |
| 102 ExtensionBookmarkEventRouter* ExtensionBookmarkEventRouter::GetSingleton() { |
| 103 return Singleton<ExtensionBookmarkEventRouter>::get(); |
| 104 } |
| 105 |
| 106 ExtensionBookmarkEventRouter::ExtensionBookmarkEventRouter() { |
| 107 } |
| 108 |
| 109 ExtensionBookmarkEventRouter::~ExtensionBookmarkEventRouter() { |
| 110 } |
| 111 |
| 112 void ExtensionBookmarkEventRouter::Observe(BookmarkModel* model) { |
| 113 if (models_.find(model) == models_.end()) { |
| 114 model->AddObserver(this); |
| 115 models_.insert(model); |
| 116 } |
| 117 } |
| 118 |
| 119 void ExtensionBookmarkEventRouter::DispatchEvent(Profile *profile, |
| 120 const char* event_name, |
| 121 const std::string json_args) { |
| 122 ExtensionMessageService::GetInstance(profile->GetRequestContext())-> |
| 123 DispatchEventToRenderers(event_name, json_args); |
| 124 } |
| 125 |
| 126 void ExtensionBookmarkEventRouter::Loaded(BookmarkModel* model) { |
| 127 // TODO(erikkay): Do we need an event here? It seems unlikely that |
| 128 // an extension would load before bookmarks loaded. |
| 129 } |
| 130 |
| 131 void ExtensionBookmarkEventRouter::BookmarkNodeMoved(BookmarkModel* model, |
| 132 BookmarkNode* old_parent, |
| 133 int old_index, |
| 134 BookmarkNode* new_parent, |
| 135 int new_index) { |
| 136 ListValue args; |
| 137 DictionaryValue* object_args = new DictionaryValue(); |
| 138 BookmarkNode* node = new_parent->GetChild(new_index); |
| 139 object_args->SetInteger(kIdKey, node->id()); |
| 140 object_args->SetInteger(kParentIdKey, new_parent->id()); |
| 141 object_args->SetInteger(kIndexKey, new_index); |
| 142 object_args->SetInteger(kOldParentIdKey, old_parent->id()); |
| 143 object_args->SetInteger(kOldIndexKey, old_index); |
| 144 args.Append(object_args); |
| 145 |
| 146 std::string json_args; |
| 147 JSONWriter::Write(&args, false, &json_args); |
| 148 DispatchEvent(model->profile(), kOnBookmarkMoved, json_args); |
| 149 } |
| 150 |
| 151 void ExtensionBookmarkEventRouter::BookmarkNodeAdded(BookmarkModel* model, |
| 152 BookmarkNode* parent, |
| 153 int index) { |
| 154 ListValue args; |
| 155 DictionaryValue* object_args = new DictionaryValue(); |
| 156 BookmarkNode* node = parent->GetChild(index); |
| 157 object_args->SetInteger(kIdKey, node->id()); |
| 158 object_args->SetString(kTitleKey, node->GetTitle()); |
| 159 object_args->SetString(kUrlKey, node->GetURL().spec()); |
| 160 object_args->SetInteger(kParentIdKey, parent->id()); |
| 161 object_args->SetInteger(kIndexKey, index); |
| 162 args.Append(object_args); |
| 163 |
| 164 std::string json_args; |
| 165 JSONWriter::Write(&args, false, &json_args); |
| 166 DispatchEvent(model->profile(), kOnBookmarkAdded, json_args); |
| 167 } |
| 168 |
| 169 void ExtensionBookmarkEventRouter::BookmarkNodeRemoved(BookmarkModel* model, |
| 170 BookmarkNode* parent, |
| 171 int index) { |
| 172 ListValue args; |
| 173 DictionaryValue* object_args = new DictionaryValue(); |
| 174 object_args->SetInteger(kParentIdKey, parent->id()); |
| 175 object_args->SetInteger(kIndexKey, index); |
| 176 args.Append(object_args); |
| 177 |
| 178 std::string json_args; |
| 179 JSONWriter::Write(&args, false, &json_args); |
| 180 DispatchEvent(model->profile(), kOnBookmarkRemoved, json_args); |
| 181 } |
| 182 |
| 183 void ExtensionBookmarkEventRouter::BookmarkNodeChanged(BookmarkModel* model, |
| 184 BookmarkNode* node) { |
| 185 ListValue args; |
| 186 args.Append(new FundamentalValue(node->id())); |
| 187 |
| 188 // TODO(erikkay) The only two things that BookmarkModel sends this |
| 189 // notification for are title and favicon. Since we're currently ignoring |
| 190 // favicon and since the notification doesn't say which one anyway, for now |
| 191 // we only include title. The ideal thing would be to change BookmarkModel |
| 192 // to indicate what changed. |
| 193 DictionaryValue* object_args = new DictionaryValue(); |
| 194 object_args->SetString(kTitleKey, node->GetTitle()); |
| 195 args.Append(object_args); |
| 196 |
| 197 std::string json_args; |
| 198 JSONWriter::Write(&args, false, &json_args); |
| 199 DispatchEvent(model->profile(), kOnBookmarkChanged, json_args); |
| 200 } |
| 201 |
| 202 void ExtensionBookmarkEventRouter::BookmarkNodeFavIconLoaded( |
| 203 BookmarkModel* model, BookmarkNode* node) { |
| 204 // TODO(erikkay) anything we should do here? |
| 205 } |
| 206 |
| 207 void ExtensionBookmarkEventRouter::BookmarkNodeChildrenReordered( |
| 208 BookmarkModel* model, BookmarkNode* node) { |
| 209 ListValue args; |
| 210 args.Append(new FundamentalValue(node->id())); |
| 211 int childCount = node->GetChildCount(); |
| 212 ListValue* children = new ListValue(); |
| 213 for (int i = 0; i < childCount; ++i) { |
| 214 BookmarkNode* child = node->GetChild(i); |
| 215 Value* child_id = new FundamentalValue(child->id()); |
| 216 children->Append(child_id); |
| 217 } |
| 218 args.Append(children); |
| 219 |
| 220 std::string json_args; |
| 221 JSONWriter::Write(&args, false, &json_args); |
| 222 DispatchEvent(model->profile(), kOnBookmarkChildrenReordered, json_args); |
| 223 } |
| 224 |
80 bool GetBookmarksFunction::RunImpl() { | 225 bool GetBookmarksFunction::RunImpl() { |
81 // TODO(erikkay): the JSON schema doesn't support the TYPE_INTEGER | 226 // TODO(erikkay): the JSON schema doesn't support the TYPE_INTEGER |
82 // variant yet. | 227 // variant yet. |
83 EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST) || | 228 EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST) || |
84 args_->IsType(Value::TYPE_INTEGER) || | 229 args_->IsType(Value::TYPE_INTEGER) || |
85 args_->IsType(Value::TYPE_NULL)); | 230 args_->IsType(Value::TYPE_NULL)); |
86 BookmarkModel* model = profile()->GetBookmarkModel(); | 231 BookmarkModel* model = profile()->GetBookmarkModel(); |
87 scoped_ptr<ListValue> json(new ListValue()); | 232 scoped_ptr<ListValue> json(new ListValue()); |
88 if (args_->IsType(Value::TYPE_INTEGER)) { | 233 if (args_->IsType(Value::TYPE_INTEGER)) { |
89 int id; | 234 int id; |
(...skipping 30 matching lines...) Loading... |
120 if (error_.size() && json->GetSize() == 0) { | 265 if (error_.size() && json->GetSize() == 0) { |
121 return false; | 266 return false; |
122 } | 267 } |
123 } | 268 } |
124 } | 269 } |
125 | 270 |
126 result_.reset(json.release()); | 271 result_.reset(json.release()); |
127 return true; | 272 return true; |
128 } | 273 } |
129 | 274 |
| 275 bool GetBookmarkChildrenFunction::RunImpl() { |
| 276 int id; |
| 277 EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&id)); |
| 278 BookmarkModel* model = profile()->GetBookmarkModel(); |
| 279 scoped_ptr<ListValue> json(new ListValue()); |
| 280 BookmarkNode* node = model->GetNodeByID(id); |
| 281 if (!node) { |
| 282 error_ = kNoNodeError; |
| 283 return false; |
| 284 } |
| 285 int child_count = node->GetChildCount(); |
| 286 for (int i = 0; i < child_count; ++i) { |
| 287 BookmarkNode* child = node->GetChild(i); |
| 288 ExtensionBookmarks::AddNode(child, json.get(), false); |
| 289 } |
| 290 |
| 291 result_.reset(json.release()); |
| 292 return true; |
| 293 } |
| 294 |
| 295 bool GetBookmarkTreeFunction::RunImpl() { |
| 296 BookmarkModel* model = profile()->GetBookmarkModel(); |
| 297 scoped_ptr<ListValue> json(new ListValue()); |
| 298 BookmarkNode* node = model->root_node(); |
| 299 ExtensionBookmarks::AddNode(node, json.get(), true); |
| 300 result_.reset(json.release()); |
| 301 return true; |
| 302 } |
| 303 |
130 bool SearchBookmarksFunction::RunImpl() { | 304 bool SearchBookmarksFunction::RunImpl() { |
131 EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_STRING)); | 305 EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_STRING)); |
132 | 306 |
133 std::wstring query; | 307 std::wstring query; |
134 EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&query)); | 308 EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&query)); |
135 | 309 |
136 BookmarkModel* model = profile()->GetBookmarkModel(); | 310 BookmarkModel* model = profile()->GetBookmarkModel(); |
137 ListValue* json = new ListValue(); | 311 ListValue* json = new ListValue(); |
138 std::vector<BookmarkNode*> nodes; | 312 std::vector<BookmarkNode*> nodes; |
139 bookmark_utils::GetBookmarksContainingText(model, query, 50, &nodes); | 313 bookmark_utils::GetBookmarksContainingText(model, query, 50, &nodes); |
(...skipping 175 matching lines...) Loading... |
315 } | 489 } |
316 if (node == model->root_node() || | 490 if (node == model->root_node() || |
317 node == model->other_node() || | 491 node == model->other_node() || |
318 node == model->GetBookmarkBarNode()) { | 492 node == model->GetBookmarkBarNode()) { |
319 error_ = kModifySpecialError; | 493 error_ = kModifySpecialError; |
320 return false; | 494 return false; |
321 } | 495 } |
322 model->SetTitle(node, title); | 496 model->SetTitle(node, title); |
323 return true; | 497 return true; |
324 } | 498 } |
325 | |
OLD | NEW |