| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/menu_manager.h" | 5 #include "chrome/browser/extensions/menu_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <tuple> | 8 #include <tuple> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 Type type, | 125 Type type, |
| 126 const ContextList& contexts) | 126 const ContextList& contexts) |
| 127 : id_(id), | 127 : id_(id), |
| 128 title_(title), | 128 title_(title), |
| 129 type_(type), | 129 type_(type), |
| 130 checked_(checked), | 130 checked_(checked), |
| 131 enabled_(enabled), | 131 enabled_(enabled), |
| 132 contexts_(contexts) {} | 132 contexts_(contexts) {} |
| 133 | 133 |
| 134 MenuItem::~MenuItem() { | 134 MenuItem::~MenuItem() { |
| 135 STLDeleteElements(&children_); | 135 base::STLDeleteElements(&children_); |
| 136 } | 136 } |
| 137 | 137 |
| 138 MenuItem* MenuItem::ReleaseChild(const Id& child_id, | 138 MenuItem* MenuItem::ReleaseChild(const Id& child_id, |
| 139 bool recursive) { | 139 bool recursive) { |
| 140 for (List::iterator i = children_.begin(); i != children_.end(); ++i) { | 140 for (List::iterator i = children_.begin(); i != children_.end(); ++i) { |
| 141 MenuItem* child = NULL; | 141 MenuItem* child = NULL; |
| 142 if ((*i)->id() == child_id) { | 142 if ((*i)->id() == child_id) { |
| 143 child = *i; | 143 child = *i; |
| 144 children_.erase(i); | 144 children_.erase(i); |
| 145 return child; | 145 return child; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 159 } | 159 } |
| 160 | 160 |
| 161 std::set<MenuItem::Id> MenuItem::RemoveAllDescendants() { | 161 std::set<MenuItem::Id> MenuItem::RemoveAllDescendants() { |
| 162 std::set<Id> result; | 162 std::set<Id> result; |
| 163 for (List::iterator i = children_.begin(); i != children_.end(); ++i) { | 163 for (List::iterator i = children_.begin(); i != children_.end(); ++i) { |
| 164 MenuItem* child = *i; | 164 MenuItem* child = *i; |
| 165 result.insert(child->id()); | 165 result.insert(child->id()); |
| 166 std::set<Id> removed = child->RemoveAllDescendants(); | 166 std::set<Id> removed = child->RemoveAllDescendants(); |
| 167 result.insert(removed.begin(), removed.end()); | 167 result.insert(removed.begin(), removed.end()); |
| 168 } | 168 } |
| 169 STLDeleteElements(&children_); | 169 base::STLDeleteElements(&children_); |
| 170 return result; | 170 return result; |
| 171 } | 171 } |
| 172 | 172 |
| 173 base::string16 MenuItem::TitleWithReplacement(const base::string16& selection, | 173 base::string16 MenuItem::TitleWithReplacement(const base::string16& selection, |
| 174 size_t max_length) const { | 174 size_t max_length) const { |
| 175 base::string16 result = base::UTF8ToUTF16(title_); | 175 base::string16 result = base::UTF8ToUTF16(title_); |
| 176 // TODO(asargent) - Change this to properly handle %% escaping so you can | 176 // TODO(asargent) - Change this to properly handle %% escaping so you can |
| 177 // put "%s" in titles that won't get substituted. | 177 // put "%s" in titles that won't get substituted. |
| 178 base::ReplaceSubstringsAfterOffset( | 178 base::ReplaceSubstringsAfterOffset( |
| 179 &result, 0, base::ASCIIToUTF16("%s"), selection); | 179 &result, 0, base::ASCIIToUTF16("%s"), selection); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); | 311 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
| 312 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 312 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 313 content::NotificationService::AllSources()); | 313 content::NotificationService::AllSources()); |
| 314 if (store_) | 314 if (store_) |
| 315 store_->RegisterKey(kContextMenusKey); | 315 store_->RegisterKey(kContextMenusKey); |
| 316 } | 316 } |
| 317 | 317 |
| 318 MenuManager::~MenuManager() { | 318 MenuManager::~MenuManager() { |
| 319 MenuItemMap::iterator i; | 319 MenuItemMap::iterator i; |
| 320 for (i = context_items_.begin(); i != context_items_.end(); ++i) { | 320 for (i = context_items_.begin(); i != context_items_.end(); ++i) { |
| 321 STLDeleteElements(&(i->second)); | 321 base::STLDeleteElements(&(i->second)); |
| 322 } | 322 } |
| 323 } | 323 } |
| 324 | 324 |
| 325 // static | 325 // static |
| 326 MenuManager* MenuManager::Get(content::BrowserContext* context) { | 326 MenuManager* MenuManager::Get(content::BrowserContext* context) { |
| 327 return MenuManagerFactory::GetForBrowserContext(context); | 327 return MenuManagerFactory::GetForBrowserContext(context); |
| 328 } | 328 } |
| 329 | 329 |
| 330 std::set<MenuItem::ExtensionKey> MenuManager::ExtensionIds() { | 330 std::set<MenuItem::ExtensionKey> MenuManager::ExtensionIds() { |
| 331 std::set<MenuItem::ExtensionKey> id_set; | 331 std::set<MenuItem::ExtensionKey> id_set; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 342 if (i != context_items_.end()) { | 342 if (i != context_items_.end()) { |
| 343 return &(i->second); | 343 return &(i->second); |
| 344 } | 344 } |
| 345 return NULL; | 345 return NULL; |
| 346 } | 346 } |
| 347 | 347 |
| 348 bool MenuManager::AddContextItem(const Extension* extension, MenuItem* item) { | 348 bool MenuManager::AddContextItem(const Extension* extension, MenuItem* item) { |
| 349 const MenuItem::ExtensionKey& key = item->id().extension_key; | 349 const MenuItem::ExtensionKey& key = item->id().extension_key; |
| 350 | 350 |
| 351 // The item must have a non-empty key, and not have already been added. | 351 // The item must have a non-empty key, and not have already been added. |
| 352 if (key.empty() || ContainsKey(items_by_id_, item->id())) | 352 if (key.empty() || base::ContainsKey(items_by_id_, item->id())) |
| 353 return false; | 353 return false; |
| 354 | 354 |
| 355 DCHECK_EQ(extension->id(), key.extension_id); | 355 DCHECK_EQ(extension->id(), key.extension_id); |
| 356 | 356 |
| 357 bool first_item = !ContainsKey(context_items_, key); | 357 bool first_item = !base::ContainsKey(context_items_, key); |
| 358 context_items_[key].push_back(item); | 358 context_items_[key].push_back(item); |
| 359 items_by_id_[item->id()] = item; | 359 items_by_id_[item->id()] = item; |
| 360 | 360 |
| 361 if (item->type() == MenuItem::RADIO) { | 361 if (item->type() == MenuItem::RADIO) { |
| 362 if (item->checked()) | 362 if (item->checked()) |
| 363 RadioItemSelected(item); | 363 RadioItemSelected(item); |
| 364 else | 364 else |
| 365 SanitizeRadioList(context_items_[key]); | 365 SanitizeRadioList(context_items_[key]); |
| 366 } | 366 } |
| 367 | 367 |
| 368 // If this is the first item for this extension, start loading its icon. | 368 // If this is the first item for this extension, start loading its icon. |
| 369 if (first_item) | 369 if (first_item) |
| 370 icon_manager_.LoadIcon(browser_context_, extension); | 370 icon_manager_.LoadIcon(browser_context_, extension); |
| 371 | 371 |
| 372 return true; | 372 return true; |
| 373 } | 373 } |
| 374 | 374 |
| 375 bool MenuManager::AddChildItem(const MenuItem::Id& parent_id, | 375 bool MenuManager::AddChildItem(const MenuItem::Id& parent_id, |
| 376 MenuItem* child) { | 376 MenuItem* child) { |
| 377 MenuItem* parent = GetItemById(parent_id); | 377 MenuItem* parent = GetItemById(parent_id); |
| 378 if (!parent || parent->type() != MenuItem::NORMAL || | 378 if (!parent || parent->type() != MenuItem::NORMAL || |
| 379 parent->incognito() != child->incognito() || | 379 parent->incognito() != child->incognito() || |
| 380 parent->extension_id() != child->extension_id() || | 380 parent->extension_id() != child->extension_id() || |
| 381 ContainsKey(items_by_id_, child->id())) | 381 base::ContainsKey(items_by_id_, child->id())) |
| 382 return false; | 382 return false; |
| 383 parent->AddChild(child); | 383 parent->AddChild(child); |
| 384 items_by_id_[child->id()] = child; | 384 items_by_id_[child->id()] = child; |
| 385 | 385 |
| 386 if (child->type() == MenuItem::RADIO) | 386 if (child->type() == MenuItem::RADIO) |
| 387 SanitizeRadioList(parent->children()); | 387 SanitizeRadioList(parent->children()); |
| 388 return true; | 388 return true; |
| 389 } | 389 } |
| 390 | 390 |
| 391 bool MenuManager::DescendantOf(MenuItem* item, | 391 bool MenuManager::DescendantOf(MenuItem* item, |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 } else { | 453 } else { |
| 454 const MenuItem::ExtensionKey& child_key = child->id().extension_key; | 454 const MenuItem::ExtensionKey& child_key = child->id().extension_key; |
| 455 context_items_[child_key].push_back(child); | 455 context_items_[child_key].push_back(child); |
| 456 child->parent_id_.reset(NULL); | 456 child->parent_id_.reset(NULL); |
| 457 SanitizeRadioList(context_items_[child_key]); | 457 SanitizeRadioList(context_items_[child_key]); |
| 458 } | 458 } |
| 459 return true; | 459 return true; |
| 460 } | 460 } |
| 461 | 461 |
| 462 bool MenuManager::RemoveContextMenuItem(const MenuItem::Id& id) { | 462 bool MenuManager::RemoveContextMenuItem(const MenuItem::Id& id) { |
| 463 if (!ContainsKey(items_by_id_, id)) | 463 if (!base::ContainsKey(items_by_id_, id)) |
| 464 return false; | 464 return false; |
| 465 | 465 |
| 466 MenuItem* menu_item = GetItemById(id); | 466 MenuItem* menu_item = GetItemById(id); |
| 467 DCHECK(menu_item); | 467 DCHECK(menu_item); |
| 468 const MenuItem::ExtensionKey extension_key = id.extension_key; | 468 const MenuItem::ExtensionKey extension_key = id.extension_key; |
| 469 MenuItemMap::iterator i = context_items_.find(extension_key); | 469 MenuItemMap::iterator i = context_items_.find(extension_key); |
| 470 if (i == context_items_.end()) { | 470 if (i == context_items_.end()) { |
| 471 NOTREACHED(); | 471 NOTREACHED(); |
| 472 return false; | 472 return false; |
| 473 } | 473 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 MenuItem* item = *i; | 537 MenuItem* item = *i; |
| 538 items_by_id_.erase(item->id()); | 538 items_by_id_.erase(item->id()); |
| 539 | 539 |
| 540 // Remove descendants from this item and erase them from the lookup cache. | 540 // Remove descendants from this item and erase them from the lookup cache. |
| 541 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants(); | 541 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants(); |
| 542 std::set<MenuItem::Id>::const_iterator j; | 542 std::set<MenuItem::Id>::const_iterator j; |
| 543 for (j = removed_ids.begin(); j != removed_ids.end(); ++j) { | 543 for (j = removed_ids.begin(); j != removed_ids.end(); ++j) { |
| 544 items_by_id_.erase(*j); | 544 items_by_id_.erase(*j); |
| 545 } | 545 } |
| 546 } | 546 } |
| 547 STLDeleteElements(&context_items_for_key); | 547 base::STLDeleteElements(&context_items_for_key); |
| 548 context_items_.erase(extension_key); | 548 context_items_.erase(extension_key); |
| 549 icon_manager_.RemoveIcon(extension_id); | 549 icon_manager_.RemoveIcon(extension_id); |
| 550 } | 550 } |
| 551 | 551 |
| 552 MenuItem* MenuManager::GetItemById(const MenuItem::Id& id) const { | 552 MenuItem* MenuManager::GetItemById(const MenuItem::Id& id) const { |
| 553 std::map<MenuItem::Id, MenuItem*>::const_iterator i = | 553 std::map<MenuItem::Id, MenuItem*>::const_iterator i = |
| 554 items_by_id_.find(id); | 554 items_by_id_.find(id); |
| 555 if (i != items_by_id_.end()) | 555 if (i != items_by_id_.end()) |
| 556 return i->second; | 556 return i->second; |
| 557 else | 557 else |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 773 if (last_checked != item_list.end()) | 773 if (last_checked != item_list.end()) |
| 774 (*last_checked)->SetChecked(true); | 774 (*last_checked)->SetChecked(true); |
| 775 else | 775 else |
| 776 (*i)->SetChecked(true); | 776 (*i)->SetChecked(true); |
| 777 | 777 |
| 778 i = radio_run_iter; | 778 i = radio_run_iter; |
| 779 } | 779 } |
| 780 } | 780 } |
| 781 | 781 |
| 782 bool MenuManager::ItemUpdated(const MenuItem::Id& id) { | 782 bool MenuManager::ItemUpdated(const MenuItem::Id& id) { |
| 783 if (!ContainsKey(items_by_id_, id)) | 783 if (!base::ContainsKey(items_by_id_, id)) |
| 784 return false; | 784 return false; |
| 785 | 785 |
| 786 MenuItem* menu_item = GetItemById(id); | 786 MenuItem* menu_item = GetItemById(id); |
| 787 DCHECK(menu_item); | 787 DCHECK(menu_item); |
| 788 | 788 |
| 789 if (menu_item->parent_id()) { | 789 if (menu_item->parent_id()) { |
| 790 SanitizeRadioList(GetItemById(*menu_item->parent_id())->children()); | 790 SanitizeRadioList(GetItemById(*menu_item->parent_id())->children()); |
| 791 } else { | 791 } else { |
| 792 MenuItemMap::iterator i = | 792 MenuItemMap::iterator i = |
| 793 context_items_.find(menu_item->id().extension_key); | 793 context_items_.find(menu_item->id().extension_key); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 kContextMenusKey, | 861 kContextMenusKey, |
| 862 base::Bind( | 862 base::Bind( |
| 863 &MenuManager::ReadFromStorage, AsWeakPtr(), extension->id())); | 863 &MenuManager::ReadFromStorage, AsWeakPtr(), extension->id())); |
| 864 } | 864 } |
| 865 } | 865 } |
| 866 | 866 |
| 867 void MenuManager::OnExtensionUnloaded(content::BrowserContext* browser_context, | 867 void MenuManager::OnExtensionUnloaded(content::BrowserContext* browser_context, |
| 868 const Extension* extension, | 868 const Extension* extension, |
| 869 UnloadedExtensionInfo::Reason reason) { | 869 UnloadedExtensionInfo::Reason reason) { |
| 870 MenuItem::ExtensionKey extension_key(extension->id()); | 870 MenuItem::ExtensionKey extension_key(extension->id()); |
| 871 if (ContainsKey(context_items_, extension_key)) { | 871 if (base::ContainsKey(context_items_, extension_key)) { |
| 872 RemoveAllContextItems(extension_key); | 872 RemoveAllContextItems(extension_key); |
| 873 } | 873 } |
| 874 } | 874 } |
| 875 | 875 |
| 876 void MenuManager::Observe(int type, | 876 void MenuManager::Observe(int type, |
| 877 const content::NotificationSource& source, | 877 const content::NotificationSource& source, |
| 878 const content::NotificationDetails& details) { | 878 const content::NotificationDetails& details) { |
| 879 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type); | 879 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type); |
| 880 Profile* profile = content::Source<Profile>(source).ptr(); | 880 Profile* profile = content::Source<Profile>(source).ptr(); |
| 881 // We cannot use profile_->HasOffTheRecordProfile as it may already be | 881 // We cannot use profile_->HasOffTheRecordProfile as it may already be |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 bool MenuItem::Id::operator!=(const Id& other) const { | 985 bool MenuItem::Id::operator!=(const Id& other) const { |
| 986 return !(*this == other); | 986 return !(*this == other); |
| 987 } | 987 } |
| 988 | 988 |
| 989 bool MenuItem::Id::operator<(const Id& other) const { | 989 bool MenuItem::Id::operator<(const Id& other) const { |
| 990 return std::tie(incognito, extension_key, uid, string_uid) < | 990 return std::tie(incognito, extension_key, uid, string_uid) < |
| 991 std::tie(other.incognito, other.extension_key, other.uid, other.string_uid); | 991 std::tie(other.incognito, other.extension_key, other.uid, other.string_uid); |
| 992 } | 992 } |
| 993 | 993 |
| 994 } // namespace extensions | 994 } // namespace extensions |
| OLD | NEW |