1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h" 6 7 #include <vector> 8 9 #include "base/lazy_instance.h" 10 #include "base/memory/linked_ptr.h" 11 #include "base/prefs/pref_service.h" 12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/utf_string_conversions.h" 14 #include "base/values.h" 15 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 16 #include "chrome/browser/bookmarks/bookmark_stats.h" 17 #include "chrome/browser/bookmarks/chrome_bookmark_client.h" 18 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h" 19 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.h" 20 #include "chrome/browser/extensions/extension_web_ui.h" 21 #include "chrome/browser/profiles/profile.h" 22 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h" 23 #include "chrome/browser/undo/bookmark_undo_service.h" 24 #include "chrome/browser/undo/bookmark_undo_service_factory.h" 25 #include "chrome/common/extensions/api/bookmark_manager_private.h" 26 #include "chrome/common/pref_names.h" 27 #include "chrome/grit/generated_resources.h" 28 #include "components/bookmarks/browser/bookmark_model.h" 29 #include "components/bookmarks/browser/bookmark_node_data.h" 30 #include "components/bookmarks/browser/bookmark_utils.h" 31 #include "components/bookmarks/browser/scoped_group_bookmark_actions.h" 32 #include "components/user_prefs/user_prefs.h" 33 #include "content/public/browser/render_view_host.h" 34 #include "content/public/browser/web_contents.h" 35 #include "content/public/browser/web_ui.h" 36 #include "extensions/browser/extension_function_dispatcher.h" 37 #include "extensions/browser/view_type_utils.h" 38 #include "ui/base/dragdrop/drag_drop_types.h" 39 #include "ui/base/l10n/l10n_util.h" 40 #include "ui/base/webui/web_ui_util.h" 41 42 using bookmarks::BookmarkNodeData; 43 44 namespace extensions { 45 46 namespace bookmark_keys = bookmark_api_constants; 47 namespace bookmark_manager_private = api::bookmark_manager_private; 48 namespace CanPaste = api::bookmark_manager_private::CanPaste; 49 namespace Copy = api::bookmark_manager_private::Copy; 50 namespace CreateWithMetaInfo = 51 api::bookmark_manager_private::CreateWithMetaInfo; 52 namespace Cut = api::bookmark_manager_private::Cut; 53 namespace Drop = api::bookmark_manager_private::Drop; 54 namespace GetSubtree = api::bookmark_manager_private::GetSubtree; 55 namespace GetMetaInfo = api::bookmark_manager_private::GetMetaInfo; 56 namespace Paste = api::bookmark_manager_private::Paste; 57 namespace RedoInfo = api::bookmark_manager_private::GetRedoInfo; 58 namespace RemoveTrees = api::bookmark_manager_private::RemoveTrees; 59 namespace SetMetaInfo = api::bookmark_manager_private::SetMetaInfo; 60 namespace SortChildren = api::bookmark_manager_private::SortChildren; 61 namespace StartDrag = api::bookmark_manager_private::StartDrag; 62 namespace UndoInfo = api::bookmark_manager_private::GetUndoInfo; 63 namespace UpdateMetaInfo = api::bookmark_manager_private::UpdateMetaInfo; 64 65 using content::WebContents; 66 67 namespace { 68 69 // Returns a single bookmark node from the argument ID. 70 // This returns NULL in case of failure. 71 const BookmarkNode* GetNodeFromString(BookmarkModel* model, 72 const std::string& id_string) { 73 int64 id; 74 if (!base::StringToInt64(id_string, &id)) 75 return NULL; 76 return bookmarks::GetBookmarkNodeByID(model, id); 77 } 78 79 // Gets a vector of bookmark nodes from the argument list of IDs. 80 // This returns false in the case of failure. 81 bool GetNodesFromVector(BookmarkModel* model, 82 const std::vector<std::string>& id_strings, 83 std::vector<const BookmarkNode*>* nodes) { 84 if (id_strings.empty()) 85 return false; 86 87 for (size_t i = 0; i < id_strings.size(); ++i) { 88 const BookmarkNode* node = GetNodeFromString(model, id_strings[i]); 89 if (!node) 90 return false; 91 nodes->push_back(node); 92 } 93 94 return true; 95 } 96 97 // Recursively create a bookmark_manager_private::BookmarkNodeDataElement from 98 // a bookmark node. This is by used |BookmarkNodeDataToJSON| when the data comes 99 // from the current profile. In this case we have a BookmarkNode since we got 100 // the data from the current profile. 101 linked_ptr<bookmark_manager_private::BookmarkNodeDataElement> 102 CreateNodeDataElementFromBookmarkNode(const BookmarkNode& node) { 103 linked_ptr<bookmark_manager_private::BookmarkNodeDataElement> element( 104 new bookmark_manager_private::BookmarkNodeDataElement); 105 // Add id and parentId so we can associate the data with existing nodes on the 106 // client side. 107 element->id.reset(new std::string(base::Int64ToString(node.id()))); 108 element->parent_id.reset( 109 new std::string(base::Int64ToString(node.parent()->id()))); 110 111 if (node.is_url()) 112 element->url.reset(new std::string(node.url().spec())); 113 114 element->title = base::UTF16ToUTF8(node.GetTitle()); 115 for (int i = 0; i < node.child_count(); ++i) { 116 element->children.push_back( 117 CreateNodeDataElementFromBookmarkNode(*node.GetChild(i))); 118 } 119 120 return element; 121 } 122 123 // Recursively create a bookmark_manager_private::BookmarkNodeDataElement from 124 // a BookmarkNodeData::Element. This is used by |BookmarkNodeDataToJSON| when 125 // the data comes from a different profile. When the data comes from a different 126 // profile we do not have any IDs or parent IDs. 127 linked_ptr<bookmark_manager_private::BookmarkNodeDataElement> 128 CreateApiNodeDataElement(const BookmarkNodeData::Element& element) { 129 linked_ptr<bookmark_manager_private::BookmarkNodeDataElement> node_element( 130 new bookmark_manager_private::BookmarkNodeDataElement); 131 132 if (element.is_url) 133 node_element->url.reset(new std::string(element.url.spec())); 134 node_element->title = base::UTF16ToUTF8(element.title); 135 for (size_t i = 0; i < element.children.size(); ++i) { 136 node_element->children.push_back( 137 CreateApiNodeDataElement(element.children[i])); 138 } 139 140 return node_element; 141 } 142 143 // Creates a bookmark_manager_private::BookmarkNodeData from a BookmarkNodeData. 144 scoped_ptr<bookmark_manager_private::BookmarkNodeData> 145 CreateApiBookmarkNodeData(Profile* profile, const BookmarkNodeData& data) { 146 const base::FilePath& profile_path = profile->GetPath(); 147 148 scoped_ptr<bookmark_manager_private::BookmarkNodeData> node_data( 149 new bookmark_manager_private::BookmarkNodeData); 150 node_data->same_profile = data.IsFromProfilePath(profile_path); 151 152 if (node_data->same_profile) { 153 std::vector<const BookmarkNode*> nodes = data.GetNodes( 154 BookmarkModelFactory::GetForProfile(profile), profile_path); 155 for (size_t i = 0; i < nodes.size(); ++i) { 156 node_data->elements.push_back( 157 CreateNodeDataElementFromBookmarkNode(*nodes[i])); 158 } 159 } else { 160 // We do not have a node IDs when the data comes from a different profile. 161 std::vector<BookmarkNodeData::Element> elements = data.elements; 162 for (size_t i = 0; i < elements.size(); ++i) 163 node_data->elements.push_back(CreateApiNodeDataElement(elements[i])); 164 } 165 return node_data.Pass(); 166 } 167 168 } // namespace 169 170 BookmarkManagerPrivateEventRouter::BookmarkManagerPrivateEventRouter( 171 content::BrowserContext* browser_context, 172 BookmarkModel* bookmark_model) 173 : browser_context_(browser_context), bookmark_model_(bookmark_model) { 174 bookmark_model_->AddObserver(this); 175 } 176 177 BookmarkManagerPrivateEventRouter::~BookmarkManagerPrivateEventRouter() { 178 if (bookmark_model_) 179 bookmark_model_->RemoveObserver(this); 180 } 181 182 void BookmarkManagerPrivateEventRouter::DispatchEvent( 183 const std::string& event_name, 184 scoped_ptr<base::ListValue> event_args) { 185 extensions::EventRouter::Get(browser_context_)->BroadcastEvent( 186 make_scoped_ptr(new extensions::Event(event_name, event_args.Pass()))); 187 } 188 189 void BookmarkManagerPrivateEventRouter::BookmarkModelChanged() {} 190 191 void BookmarkManagerPrivateEventRouter::BookmarkModelBeingDeleted( 192 BookmarkModel* model) { 193 bookmark_model_ = NULL; 194 } 195 196 void BookmarkManagerPrivateEventRouter::OnWillChangeBookmarkMetaInfo( 197 BookmarkModel* model, 198 const BookmarkNode* node) { 199 DCHECK(prev_meta_info_.empty()); 200 if (node->GetMetaInfoMap()) 201 prev_meta_info_ = *node->GetMetaInfoMap(); 202 } 203 204 void BookmarkManagerPrivateEventRouter::BookmarkMetaInfoChanged( 205 BookmarkModel* model, 206 const BookmarkNode* node) { 207 const BookmarkNode::MetaInfoMap* new_meta_info = node->GetMetaInfoMap(); 208 bookmark_manager_private::MetaInfoFields changes; 209 210 // Identify changed/removed fields: 211 for (BookmarkNode::MetaInfoMap::const_iterator it = prev_meta_info_.begin(); 212 it != prev_meta_info_.end(); 213 ++it) { 214 if (!new_meta_info) { 215 changes.additional_properties[it->first] = ""; 216 } else { 217 BookmarkNode::MetaInfoMap::const_iterator new_meta_field = 218 new_meta_info->find(it->first); 219 if (new_meta_field == new_meta_info->end()) { 220 changes.additional_properties[it->first] = ""; 221 } else if (it->second != new_meta_field->second) { 222 changes.additional_properties[it->first] = new_meta_field->second; 223 } 224 } 225 } 226 227 // Identify added fields: 228 if (new_meta_info) { 229 for (BookmarkNode::MetaInfoMap::const_iterator it = new_meta_info->begin(); 230 it != new_meta_info->end(); 231 ++it) { 232 BookmarkNode::MetaInfoMap::const_iterator prev_meta_field = 233 prev_meta_info_.find(it->first); 234 if (prev_meta_field == prev_meta_info_.end()) 235 changes.additional_properties[it->first] = it->second; 236 } 237 } 238 239 prev_meta_info_.clear(); 240 DispatchEvent(bookmark_manager_private::OnMetaInfoChanged::kEventName, 241 bookmark_manager_private::OnMetaInfoChanged::Create( 242 base::Int64ToString(node->id()), changes)); 243 } 244 245 BookmarkManagerPrivateAPI::BookmarkManagerPrivateAPI( 246 content::BrowserContext* browser_context) 247 : browser_context_(browser_context) { 248 EventRouter* event_router = EventRouter::Get(browser_context); 249 event_router->RegisterObserver( 250 this, bookmark_manager_private::OnMetaInfoChanged::kEventName); 251 } 252 253 BookmarkManagerPrivateAPI::~BookmarkManagerPrivateAPI() {} 254 255 void BookmarkManagerPrivateAPI::Shutdown() { 256 EventRouter::Get(browser_context_)->UnregisterObserver(this); 257 } 258 259 static base::LazyInstance< 260 BrowserContextKeyedAPIFactory<BookmarkManagerPrivateAPI> > g_factory = 261 LAZY_INSTANCE_INITIALIZER; 262 263 // static 264 BrowserContextKeyedAPIFactory<BookmarkManagerPrivateAPI>* 265 BookmarkManagerPrivateAPI::GetFactoryInstance() { 266 return g_factory.Pointer(); 267 } 268 269 void BookmarkManagerPrivateAPI::OnListenerAdded( 270 const EventListenerInfo& details) { 271 EventRouter::Get(browser_context_)->UnregisterObserver(this); 272 event_router_.reset(new BookmarkManagerPrivateEventRouter( 273 browser_context_, 274 BookmarkModelFactory::GetForProfile( 275 Profile::FromBrowserContext(browser_context_)))); 276 } 277 278 BookmarkManagerPrivateDragEventRouter::BookmarkManagerPrivateDragEventRouter( 279 Profile* profile, 280 content::WebContents* web_contents) 281 : profile_(profile), web_contents_(web_contents) { 282 BookmarkTabHelper* bookmark_tab_helper = 283 BookmarkTabHelper::FromWebContents(web_contents_); 284 bookmark_tab_helper->set_bookmark_drag_delegate(this); 285 } 286 287 BookmarkManagerPrivateDragEventRouter:: 288 ~BookmarkManagerPrivateDragEventRouter() { 289 BookmarkTabHelper* bookmark_tab_helper = 290 BookmarkTabHelper::FromWebContents(web_contents_); 291 if (bookmark_tab_helper->bookmark_drag_delegate() == this) 292 bookmark_tab_helper->set_bookmark_drag_delegate(NULL); 293 } 294 295 void BookmarkManagerPrivateDragEventRouter::DispatchEvent( 296 const std::string& event_name, 297 scoped_ptr<base::ListValue> args) { 298 EventRouter* event_router = EventRouter::Get(profile_); 299 if (!event_router) 300 return; 301 302 scoped_ptr<Event> event(new Event(event_name, args.Pass())); 303 event_router->BroadcastEvent(event.Pass()); 304 } 305 306 void BookmarkManagerPrivateDragEventRouter::OnDragEnter( 307 const BookmarkNodeData& data) { 308 if (data.size() == 0) 309 return; 310 DispatchEvent(bookmark_manager_private::OnDragEnter::kEventName, 311 bookmark_manager_private::OnDragEnter::Create( 312 *CreateApiBookmarkNodeData(profile_, data))); 313 } 314 315 void BookmarkManagerPrivateDragEventRouter::OnDragOver( 316 const BookmarkNodeData& data) { 317 // Intentionally empty since these events happens too often and floods the 318 // message queue. We do not need this event for the bookmark manager anyway. 319 } 320 321 void BookmarkManagerPrivateDragEventRouter::OnDragLeave( 322 const BookmarkNodeData& data) { 323 if (data.size() == 0) 324 return; 325 DispatchEvent(bookmark_manager_private::OnDragLeave::kEventName, 326 bookmark_manager_private::OnDragLeave::Create( 327 *CreateApiBookmarkNodeData(profile_, data))); 328 } 329 330 void BookmarkManagerPrivateDragEventRouter::OnDrop( 331 const BookmarkNodeData& data) { 332 if (data.size() == 0) 333 return; 334 DispatchEvent(bookmark_manager_private::OnDrop::kEventName, 335 bookmark_manager_private::OnDrop::Create( 336 *CreateApiBookmarkNodeData(profile_, data))); 337 338 // Make a copy that is owned by this instance. 339 ClearBookmarkNodeData(); 340 bookmark_drag_data_ = data; 341 } 342 343 const BookmarkNodeData* 344 BookmarkManagerPrivateDragEventRouter::GetBookmarkNodeData() { 345 if (bookmark_drag_data_.is_valid()) 346 return &bookmark_drag_data_; 347 return NULL; 348 } 349 350 void BookmarkManagerPrivateDragEventRouter::ClearBookmarkNodeData() { 351 bookmark_drag_data_.Clear(); 352 } 353 354 bool ClipboardBookmarkManagerFunction::CopyOrCut(bool cut, 355 const std::vector<std::string>& id_list) { 356 BookmarkModel* model = GetBookmarkModel(); 357 ChromeBookmarkClient* client = GetChromeBookmarkClient(); 358 std::vector<const BookmarkNode*> nodes; 359 EXTENSION_FUNCTION_VALIDATE(GetNodesFromVector(model, id_list, &nodes)); 360 if (cut && client->HasDescendantsOfManagedNode(nodes)) { 361 error_ = bookmark_keys::kModifyManagedError; 362 return false; 363 } 364 bookmarks::CopyToClipboard(model, nodes, cut); 365 return true; 366 } 367 368 bool BookmarkManagerPrivateCopyFunction::RunOnReady() { 369 scoped_ptr<Copy::Params> params(Copy::Params::Create(*args_)); 370 EXTENSION_FUNCTION_VALIDATE(params); 371 return CopyOrCut(false, params->id_list); 372 } 373 374 bool BookmarkManagerPrivateCutFunction::RunOnReady() { 375 if (!EditBookmarksEnabled()) 376 return false; 377 378 scoped_ptr<Cut::Params> params(Cut::Params::Create(*args_)); 379 EXTENSION_FUNCTION_VALIDATE(params); 380 return CopyOrCut(true, params->id_list); 381 } 382 383 bool BookmarkManagerPrivatePasteFunction::RunOnReady() { 384 if (!EditBookmarksEnabled()) 385 return false; 386 387 scoped_ptr<Paste::Params> params(Paste::Params::Create(*args_)); 388 EXTENSION_FUNCTION_VALIDATE(params); 389 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 390 const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id); 391 if (!CanBeModified(parent_node)) 392 return false; 393 bool can_paste = bookmarks::CanPasteFromClipboard(model, parent_node); 394 if (!can_paste) 395 return false; 396 397 // We want to use the highest index of the selected nodes as a destination. 398 std::vector<const BookmarkNode*> nodes; 399 // No need to test return value, if we got an empty list, we insert at end. 400 if (params->selected_id_list) 401 GetNodesFromVector(model, *params->selected_id_list, &nodes); 402 int highest_index = -1; // -1 means insert at end of list. 403 for (size_t i = 0; i < nodes.size(); ++i) { 404 // + 1 so that we insert after the selection. 405 int index = parent_node->GetIndexOf(nodes[i]) + 1; 406 if (index > highest_index) 407 highest_index = index; 408 } 409 410 bookmarks::PasteFromClipboard(model, parent_node, highest_index); 411 return true; 412 } 413 414 bool BookmarkManagerPrivateCanPasteFunction::RunOnReady() { 415 if (!EditBookmarksEnabled()) 416 return false; 417 418 scoped_ptr<CanPaste::Params> params(CanPaste::Params::Create(*args_)); 419 EXTENSION_FUNCTION_VALIDATE(params); 420 421 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 422 const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id); 423 if (!parent_node) { 424 error_ = bookmark_keys::kNoParentError; 425 return false; 426 } 427 bool can_paste = bookmarks::CanPasteFromClipboard(model, parent_node); 428 SetResult(new base::FundamentalValue(can_paste)); 429 return true; 430 } 431 432 bool BookmarkManagerPrivateSortChildrenFunction::RunOnReady() { 433 if (!EditBookmarksEnabled()) 434 return false; 435 436 scoped_ptr<SortChildren::Params> params(SortChildren::Params::Create(*args_)); 437 EXTENSION_FUNCTION_VALIDATE(params); 438 439 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 440 const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id); 441 if (!CanBeModified(parent_node)) 442 return false; 443 model->SortChildren(parent_node); 444 return true; 445 } 446 447 bool BookmarkManagerPrivateGetStringsFunction::RunAsync() { 448 base::DictionaryValue* localized_strings = new base::DictionaryValue(); 449 450 localized_strings->SetString("title", 451 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TITLE)); 452 localized_strings->SetString("search_button", 453 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH_BUTTON)); 454 localized_strings->SetString("organize_menu", 455 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU)); 456 localized_strings->SetString("show_in_folder", 457 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); 458 localized_strings->SetString("sort", 459 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SORT)); 460 localized_strings->SetString("import_menu", 461 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_IMPORT_MENU)); 462 localized_strings->SetString("export_menu", 463 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_EXPORT_MENU)); 464 localized_strings->SetString("rename_folder", 465 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_RENAME_FOLDER)); 466 localized_strings->SetString("edit", 467 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_EDIT)); 468 localized_strings->SetString("should_open_all", 469 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL)); 470 localized_strings->SetString("open_incognito", 471 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_INCOGNITO)); 472 localized_strings->SetString("open_in_new_tab", 473 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB)); 474 localized_strings->SetString("open_in_new_window", 475 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW)); 476 localized_strings->SetString("add_new_bookmark", 477 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK)); 478 localized_strings->SetString("new_folder", 479 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_NEW_FOLDER)); 480 localized_strings->SetString("open_all", 481 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL)); 482 localized_strings->SetString("open_all_new_window", 483 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW)); 484 localized_strings->SetString("open_all_incognito", 485 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO)); 486 localized_strings->SetString("remove", 487 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_REMOVE)); 488 localized_strings->SetString("copy", 489 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_COPY)); 490 localized_strings->SetString("cut", 491 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_CUT)); 492 localized_strings->SetString("paste", 493 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PASTE)); 494 localized_strings->SetString("delete", 495 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_DELETE)); 496 localized_strings->SetString("undo_delete", 497 l10n_util::GetStringUTF16(IDS_UNDO_DELETE)); 498 localized_strings->SetString("new_folder_name", 499 l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME)); 500 localized_strings->SetString("name_input_placeholder", 501 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER)); 502 localized_strings->SetString("url_input_placeholder", 503 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_URL_INPUT_PLACE_HOLDER)); 504 localized_strings->SetString("invalid_url", 505 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_INVALID_URL)); 506 localized_strings->SetString("recent", 507 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_RECENT)); 508 localized_strings->SetString("search", 509 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH)); 510 localized_strings->SetString("save", 511 l10n_util::GetStringUTF16(IDS_SAVE)); 512 localized_strings->SetString("cancel", 513 l10n_util::GetStringUTF16(IDS_CANCEL)); 514 515 webui::SetFontAndTextDirection(localized_strings); 516 517 SetResult(localized_strings); 518 519 // This is needed because unlike the rest of these functions, this class 520 // inherits from AsyncFunction directly, rather than BookmarkFunction. 521 SendResponse(true); 522 523 return true; 524 } 525 526 bool BookmarkManagerPrivateStartDragFunction::RunOnReady() { 527 if (!EditBookmarksEnabled()) 528 return false; 529 530 scoped_ptr<StartDrag::Params> params(StartDrag::Params::Create(*args_)); 531 EXTENSION_FUNCTION_VALIDATE(params); 532 533 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 534 std::vector<const BookmarkNode*> nodes; 535 EXTENSION_FUNCTION_VALIDATE( 536 GetNodesFromVector(model, params->id_list, &nodes)); 537 538 WebContents* web_contents = 539 WebContents::FromRenderViewHost(render_view_host_); 540 if (GetViewType(web_contents) == VIEW_TYPE_TAB_CONTENTS) { 541 WebContents* web_contents = 542 dispatcher()->delegate()->GetAssociatedWebContents(); 543 CHECK(web_contents); 544 545 ui::DragDropTypes::DragEventSource source = 546 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE; 547 if (params->is_from_touch) 548 source = ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH; 549 550 chrome::DragBookmarks( 551 GetProfile(), nodes, web_contents->GetNativeView(), source); 552 553 return true; 554 } else { 555 NOTREACHED(); 556 return false; 557 } 558 } 559 560 bool BookmarkManagerPrivateDropFunction::RunOnReady() { 561 if (!EditBookmarksEnabled()) 562 return false; 563 564 scoped_ptr<Drop::Params> params(Drop::Params::Create(*args_)); 565 EXTENSION_FUNCTION_VALIDATE(params); 566 567 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 568 569 const BookmarkNode* drop_parent = GetNodeFromString(model, params->parent_id); 570 if (!CanBeModified(drop_parent)) 571 return false; 572 573 int drop_index; 574 if (params->index) 575 drop_index = *params->index; 576 else 577 drop_index = drop_parent->child_count(); 578 579 WebContents* web_contents = 580 WebContents::FromRenderViewHost(render_view_host_); 581 if (GetViewType(web_contents) == VIEW_TYPE_TAB_CONTENTS) { 582 WebContents* web_contents = 583 dispatcher()->delegate()->GetAssociatedWebContents(); 584 CHECK(web_contents); 585 ExtensionWebUI* web_ui = 586 static_cast<ExtensionWebUI*>(web_contents->GetWebUI()->GetController()); 587 CHECK(web_ui); 588 BookmarkManagerPrivateDragEventRouter* router = 589 web_ui->bookmark_manager_private_drag_event_router(); 590 591 DCHECK(router); 592 const BookmarkNodeData* drag_data = router->GetBookmarkNodeData(); 593 if (drag_data == NULL) { 594 NOTREACHED() <<"Somehow we're dropping null bookmark data"; 595 return false; 596 } 597 const bool copy = false; 598 chrome::DropBookmarks( 599 GetProfile(), *drag_data, drop_parent, drop_index, copy); 600 601 router->ClearBookmarkNodeData(); 602 return true; 603 } else { 604 NOTREACHED(); 605 return false; 606 } 607 } 608 609 bool BookmarkManagerPrivateGetSubtreeFunction::RunOnReady() { 610 scoped_ptr<GetSubtree::Params> params(GetSubtree::Params::Create(*args_)); 611 EXTENSION_FUNCTION_VALIDATE(params); 612 613 const BookmarkNode* node = NULL; 614 615 if (params->id == "") { 616 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 617 node = model->root_node(); 618 } else { 619 node = GetBookmarkNodeFromId(params->id); 620 if (!node) 621 return false; 622 } 623 624 std::vector<linked_ptr<api::bookmarks::BookmarkTreeNode> > nodes; 625 ChromeBookmarkClient* client = GetChromeBookmarkClient(); 626 if (params->folders_only) 627 bookmark_api_helpers::AddNodeFoldersOnly(client, node, &nodes, true); 628 else 629 bookmark_api_helpers::AddNode(client, node, &nodes, true); 630 results_ = GetSubtree::Results::Create(nodes); 631 return true; 632 } 633 634 bool BookmarkManagerPrivateCanEditFunction::RunOnReady() { 635 PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile()); 636 SetResult(new base::FundamentalValue( 637 prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled))); 638 return true; 639 } 640 641 bool BookmarkManagerPrivateRecordLaunchFunction::RunOnReady() { 642 RecordBookmarkLaunch(NULL, BOOKMARK_LAUNCH_LOCATION_MANAGER); 643 return true; 644 } 645 646 bool BookmarkManagerPrivateCreateWithMetaInfoFunction::RunOnReady() { 647 scoped_ptr<CreateWithMetaInfo::Params> params( 648 CreateWithMetaInfo::Params::Create(*args_)); 649 EXTENSION_FUNCTION_VALIDATE(params); 650 651 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 652 const BookmarkNode* node = CreateBookmarkNode( 653 model, params->bookmark, ¶ms->meta_info.additional_properties); 654 if (!node) 655 return false; 656 657 scoped_ptr<api::bookmarks::BookmarkTreeNode> result_node( 658 bookmark_api_helpers::GetBookmarkTreeNode( 659 GetChromeBookmarkClient(), node, false, false)); 660 results_ = CreateWithMetaInfo::Results::Create(*result_node); 661 662 return true; 663 } 664 665 bool BookmarkManagerPrivateGetMetaInfoFunction::RunOnReady() { 666 scoped_ptr<GetMetaInfo::Params> params(GetMetaInfo::Params::Create(*args_)); 667 EXTENSION_FUNCTION_VALIDATE(params); 668 669 if (params->id) { 670 const BookmarkNode* node = GetBookmarkNodeFromId(*params->id); 671 if (!node) 672 return false; 673 674 if (params->key) { 675 std::string value; 676 if (node->GetMetaInfo(*params->key, &value)) { 677 GetMetaInfo::Results::Value result; 678 result.as_string.reset(new std::string(value)); 679 results_ = GetMetaInfo::Results::Create(result); 680 } 681 } else { 682 GetMetaInfo::Results::Value result; 683 result.as_object.reset(new GetMetaInfo::Results::Value::Object); 684 685 const BookmarkNode::MetaInfoMap* meta_info = node->GetMetaInfoMap(); 686 if (meta_info) { 687 BookmarkNode::MetaInfoMap::const_iterator itr; 688 base::DictionaryValue& temp = result.as_object->additional_properties; 689 for (itr = meta_info->begin(); itr != meta_info->end(); itr++) { 690 temp.SetStringWithoutPathExpansion(itr->first, itr->second); 691 } 692 } 693 results_ = GetMetaInfo::Results::Create(result); 694 } 695 } else { 696 if (params->key) { 697 error_ = bookmark_api_constants::kInvalidParamError; 698 return true; 699 } 700 701 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 702 const BookmarkNode* node = model->root_node(); 703 704 GetMetaInfo::Results::Value result; 705 result.as_object.reset(new GetMetaInfo::Results::Value::Object); 706 707 bookmark_api_helpers::GetMetaInfo(*node, 708 &result.as_object->additional_properties); 709 710 results_ = GetMetaInfo::Results::Create(result); 711 } 712 713 return true; 714 } 715 716 bool BookmarkManagerPrivateSetMetaInfoFunction::RunOnReady() { 717 scoped_ptr<SetMetaInfo::Params> params(SetMetaInfo::Params::Create(*args_)); 718 EXTENSION_FUNCTION_VALIDATE(params); 719 720 const BookmarkNode* node = GetBookmarkNodeFromId(params->id); 721 if (!node) 722 return false; 723 724 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 725 model->SetNodeMetaInfo(node, params->key, params->value); 726 return true; 727 } 728 729 bool BookmarkManagerPrivateUpdateMetaInfoFunction::RunOnReady() { 730 scoped_ptr<UpdateMetaInfo::Params> params( 731 UpdateMetaInfo::Params::Create(*args_)); 732 EXTENSION_FUNCTION_VALIDATE(params); 733 734 const BookmarkNode* node = GetBookmarkNodeFromId(params->id); 735 if (!node) 736 return false; 737 738 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile()); 739 BookmarkNode::MetaInfoMap new_meta_info( 740 params->meta_info_changes.additional_properties); 741 if (node->GetMetaInfoMap()) { 742 new_meta_info.insert(node->GetMetaInfoMap()->begin(), 743 node->GetMetaInfoMap()->end()); 744 } 745 model->SetNodeMetaInfoMap(node, new_meta_info); 746 747 return true; 748 } 749 750 bool BookmarkManagerPrivateCanOpenNewWindowsFunction::RunOnReady() { 751 bool can_open_new_windows = true; 752 SetResult(new base::FundamentalValue(can_open_new_windows)); 753 return true; 754 } 755 756 bool BookmarkManagerPrivateRemoveTreesFunction::RunOnReady() { 757 scoped_ptr<RemoveTrees::Params> params(RemoveTrees::Params::Create(*args_)); 758 EXTENSION_FUNCTION_VALIDATE(params); 759 760 BookmarkModel* model = GetBookmarkModel(); 761 ChromeBookmarkClient* client = GetChromeBookmarkClient(); 762 bookmarks::ScopedGroupBookmarkActions group_deletes(model); 763 int64 id; 764 for (size_t i = 0; i < params->id_list.size(); ++i) { 765 if (!GetBookmarkIdAsInt64(params->id_list[i], &id)) 766 return false; 767 if (!bookmark_api_helpers::RemoveNode(model, client, id, true, &error_)) 768 return false; 769 } 770 771 return true; 772 } 773 774 bool BookmarkManagerPrivateUndoFunction::RunOnReady() { 775 BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()-> 776 Undo(); 777 return true; 778 } 779 780 bool BookmarkManagerPrivateRedoFunction::RunOnReady() { 781 BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()-> 782 Redo(); 783 return true; 784 } 785 786 bool BookmarkManagerPrivateGetUndoInfoFunction::RunOnReady() { 787 UndoManager* undo_manager = 788 BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager(); 789 790 UndoInfo::Results::Result result; 791 result.enabled = undo_manager->undo_count() > 0; 792 result.label = base::UTF16ToUTF8(undo_manager->GetUndoLabel()); 793 794 results_ = UndoInfo::Results::Create(result); 795 return true; 796 } 797 798 bool BookmarkManagerPrivateGetRedoInfoFunction::RunOnReady() { 799 UndoManager* undo_manager = 800 BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager(); 801 802 RedoInfo::Results::Result result; 803 result.enabled = undo_manager->redo_count() > 0; 804 result.label = base::UTF16ToUTF8(undo_manager->GetRedoLabel()); 805 806 results_ = RedoInfo::Results::Create(result); 807 return true; 808 } 809 810 } // namespace extensions 811