Chromium Code Reviews| Index: chrome/browser/extensions/menu_manager.cc |
| diff --git a/chrome/browser/extensions/menu_manager.cc b/chrome/browser/extensions/menu_manager.cc |
| index 424366390b34035298c5790bd32d417cd7ed67a8..fa555315925b27f4d75cfa9459b2e195c29da336 100644 |
| --- a/chrome/browser/extensions/menu_manager.cc |
| +++ b/chrome/browser/extensions/menu_manager.cc |
| @@ -19,6 +19,7 @@ |
| #include "chrome/browser/extensions/menu_manager_factory.h" |
| #include "chrome/browser/extensions/state_store.h" |
| #include "chrome/browser/extensions/tab_helper.h" |
| +#include "chrome/browser/guestview/webview/webview_guest.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/extensions/api/context_menus.h" |
| #include "content/public/browser/notification_details.h" |
| @@ -322,40 +323,38 @@ std::set<std::string> MenuManager::ExtensionIds() { |
| std::set<std::string> id_set; |
| for (MenuItemMap::const_iterator i = context_items_.begin(); |
| i != context_items_.end(); ++i) { |
| - id_set.insert(i->first); |
| + id_set.insert(i->first.extension_id); |
| } |
| return id_set; |
| } |
| const MenuItem::List* MenuManager::MenuItems( |
| - const std::string& extension_id) { |
| - MenuItemMap::iterator i = context_items_.find(extension_id); |
| + const MenuItem::ExtensionKey& key) { |
| + MenuItemMap::iterator i = context_items_.find(key); |
| if (i != context_items_.end()) { |
| return &(i->second); |
| } |
| return NULL; |
| } |
| -bool MenuManager::AddContextItem( |
| - const Extension* extension, |
| - MenuItem* item) { |
| - const std::string& extension_id = item->extension_id(); |
| +bool MenuManager::AddContextItem(const Extension* extension, MenuItem* item) { |
| + const MenuItem::ExtensionKey& key = item->id().extension_key; |
| // The item must have a non-empty extension id, and not have already been |
| // added. |
| - if (extension_id.empty() || ContainsKey(items_by_id_, item->id())) |
| + if (key.empty() || ContainsKey(items_by_id_, item->id())) |
| return false; |
| - DCHECK_EQ(extension->id(), extension_id); |
| + DCHECK_EQ(extension->id(), key.extension_id); |
| - bool first_item = !ContainsKey(context_items_, extension_id); |
| - context_items_[extension_id].push_back(item); |
| + bool first_item = !ContainsKey(context_items_, key); |
| + context_items_[key].push_back(item); |
| items_by_id_[item->id()] = item; |
| if (item->type() == MenuItem::RADIO) { |
| if (item->checked()) |
| RadioItemSelected(item); |
| else |
| - SanitizeRadioList(context_items_[extension_id]); |
| + SanitizeRadioList(context_items_[key]); |
| } |
| // If this is the first item for this extension, start loading its icon. |
| @@ -424,14 +423,14 @@ bool MenuManager::ChangeParent(const MenuItem::Id& child_id, |
| } else { |
| // This is a top-level item, so we need to pull it out of our list of |
| // top-level items. |
| - MenuItemMap::iterator i = context_items_.find(child->extension_id()); |
| + const MenuItem::ExtensionKey& child_key = child->id().extension_key; |
| + MenuItemMap::iterator i = context_items_.find(child_key); |
| if (i == context_items_.end()) { |
| NOTREACHED(); |
| return false; |
| } |
| MenuItem::List& list = i->second; |
| - MenuItem::List::iterator j = std::find(list.begin(), list.end(), |
| - child); |
| + MenuItem::List::iterator j = std::find(list.begin(), list.end(), child); |
| if (j == list.end()) { |
| NOTREACHED(); |
| return false; |
| @@ -444,9 +443,10 @@ bool MenuManager::ChangeParent(const MenuItem::Id& child_id, |
| new_parent->AddChild(child); |
| SanitizeRadioList(new_parent->children()); |
| } else { |
| - context_items_[child->extension_id()].push_back(child); |
| + const MenuItem::ExtensionKey& child_key = child->id().extension_key; |
| + context_items_[child_key].push_back(child); |
| child->parent_id_.reset(NULL); |
| - SanitizeRadioList(context_items_[child->extension_id()]); |
| + SanitizeRadioList(context_items_[child_key]); |
| } |
| return true; |
| } |
| @@ -457,8 +457,7 @@ bool MenuManager::RemoveContextMenuItem(const MenuItem::Id& id) { |
| MenuItem* menu_item = GetItemById(id); |
| DCHECK(menu_item); |
| - std::string extension_id = menu_item->extension_id(); |
| - MenuItemMap::iterator i = context_items_.find(extension_id); |
| + MenuItemMap::iterator i = context_items_.find(id.extension_key); |
| if (i == context_items_.end()) { |
| NOTREACHED(); |
| return false; |
| @@ -503,16 +502,18 @@ bool MenuManager::RemoveContextMenuItem(const MenuItem::Id& id) { |
| } |
| if (list.empty()) { |
| - context_items_.erase(extension_id); |
| - icon_manager_.RemoveIcon(extension_id); |
| + context_items_.erase(id.extension_key); |
| + icon_manager_.RemoveIcon(id.extension_key.extension_id); |
| } |
| return result; |
| } |
| -void MenuManager::RemoveAllContextItems(const std::string& extension_id) { |
| +void MenuManager::RemoveAllContextItems( |
| + const MenuItem::ExtensionKey& extension_key) { |
| MenuItem::List::iterator i; |
| - for (i = context_items_[extension_id].begin(); |
| - i != context_items_[extension_id].end(); ++i) { |
| + for (i = context_items_[extension_key].begin(); |
| + i != context_items_[extension_key].end(); |
| + ++i) { |
| MenuItem* item = *i; |
| items_by_id_.erase(item->id()); |
| @@ -523,9 +524,9 @@ void MenuManager::RemoveAllContextItems(const std::string& extension_id) { |
| items_by_id_.erase(*j); |
| } |
| } |
| - STLDeleteElements(&context_items_[extension_id]); |
| - context_items_.erase(extension_id); |
| - icon_manager_.RemoveIcon(extension_id); |
| + STLDeleteElements(&context_items_[extension_key]); |
| + context_items_.erase(extension_key); |
| + icon_manager_.RemoveIcon(extension_key.extension_id); |
| } |
| MenuItem* MenuManager::GetItemById(const MenuItem::Id& id) const { |
| @@ -549,11 +550,12 @@ void MenuManager::RadioItemSelected(MenuItem* item) { |
| } |
| list = &(parent->children()); |
| } else { |
| - if (context_items_.find(item->extension_id()) == context_items_.end()) { |
| + const MenuItem::ExtensionKey& key = item->id().extension_key; |
| + if (context_items_.find(key) == context_items_.end()) { |
| NOTREACHED(); |
| return; |
| } |
| - list = &context_items_[item->extension_id()]; |
| + list = &context_items_[key]; |
| } |
| // Find where |item| is in the list. |
| @@ -610,8 +612,8 @@ void MenuManager::ExecuteCommand(Profile* profile, |
| // ExtensionService/Extension can be NULL in unit tests :( |
| ExtensionService* service = |
| ExtensionSystem::Get(profile_)->extension_service(); |
| - const Extension* extension = service ? |
| - service->extensions()->GetByID(menu_item_id.extension_id) : NULL; |
| + const Extension* extension = |
| + service ? service->extensions()->GetByID(item->extension_id()) : NULL; |
| if (item->type() == MenuItem::RADIO) |
| RadioItemSelected(item); |
| @@ -646,6 +648,14 @@ void MenuManager::ExecuteCommand(Profile* profile, |
| properties->SetBoolean("editable", params.is_editable); |
| + WebViewGuest* webview_guest = WebViewGuest::FromWebContents(web_contents); |
| + if (webview_guest) { |
| + // This is used in webview_custom_bindings.js. |
| + // The property is not exposed to developer API. |
| + properties->SetInteger("webviewInstanceId", |
| + webview_guest->view_instance_id()); |
| + } |
| + |
| args->Append(properties); |
| // Add the tab info to the argument list. |
| @@ -673,7 +683,7 @@ void MenuManager::ExecuteCommand(Profile* profile, |
| properties->SetBoolean("checked", item->checked()); |
| if (extension) |
| - WriteToStorage(extension); |
| + WriteToStorage(extension, item->id().extension_key); |
| } |
| // Note: web_contents are NULL in unit tests :( |
| @@ -683,6 +693,7 @@ void MenuManager::ExecuteCommand(Profile* profile, |
| } |
| { |
| + // Dispatch to menu item's .onclick handler. |
| scoped_ptr<Event> event(new Event( |
| event_names::kOnContextMenus, |
| scoped_ptr<base::ListValue>(args->DeepCopy()))); |
| @@ -691,10 +702,15 @@ void MenuManager::ExecuteCommand(Profile* profile, |
| event_router->DispatchEventToExtension(item->extension_id(), event.Pass()); |
| } |
| { |
| - scoped_ptr<Event> event(new Event(context_menus::OnClicked::kEventName, |
| - args.Pass())); |
| + // Dispatch to .contextMenus.onClicked handler. |
| + scoped_ptr<Event> event( |
| + new Event(webview_guest ? event_names::kOnWebviewContextMenus |
| + : context_menus::OnClicked::kEventName, |
| + args.Pass())); |
| event->restrict_to_browser_context = profile; |
| event->user_gesture = EventRouter::USER_GESTURE_ENABLED; |
| + if (webview_guest) |
| + event->filter_info.SetInstanceID(webview_guest->view_instance_id()); |
| event_router->DispatchEventToExtension(item->extension_id(), event.Pass()); |
| } |
| } |
| @@ -743,8 +759,8 @@ bool MenuManager::ItemUpdated(const MenuItem::Id& id) { |
| if (menu_item->parent_id()) { |
| SanitizeRadioList(GetItemById(*menu_item->parent_id())->children()); |
| } else { |
| - std::string extension_id = menu_item->extension_id(); |
| - MenuItemMap::iterator i = context_items_.find(extension_id); |
| + MenuItemMap::iterator i = |
| + context_items_.find(menu_item->id().extension_key); |
| if (i == context_items_.end()) { |
| NOTREACHED(); |
| return false; |
| @@ -755,21 +771,26 @@ bool MenuManager::ItemUpdated(const MenuItem::Id& id) { |
| return true; |
| } |
| -void MenuManager::WriteToStorage(const Extension* extension) { |
| +void MenuManager::WriteToStorage(const Extension* extension, |
| + const MenuItem::ExtensionKey& extension_key) { |
| if (!BackgroundInfo::HasLazyBackgroundPage(extension)) |
| return; |
| - const MenuItem::List* top_items = MenuItems(extension->id()); |
| + if (extension_key.webview_instance_id) |
|
Fady Samuel
2014/03/05 17:54:10
A comment above this would be useful.
lazyboy
2014/03/05 18:27:59
Done.
|
| + return; |
| + const MenuItem::List* top_items = MenuItems(extension_key); |
| MenuItem::List all_items; |
| if (top_items) { |
| for (MenuItem::List::const_iterator i = top_items->begin(); |
| i != top_items->end(); ++i) { |
| + DCHECK(!(*i)->id().extension_key.webview_instance_id); |
| (*i)->GetFlattenedSubtree(&all_items); |
| } |
| } |
| - if (store_) |
| + if (store_) { |
| store_->SetExtensionValue(extension->id(), kContextMenusKey, |
| MenuItemsToValue(all_items)); |
| + } |
| } |
| void MenuManager::ReadFromStorage(const std::string& extension_id, |
| @@ -804,8 +825,9 @@ void MenuManager::Observe(int type, |
| // Remove menu items for disabled/uninstalled extensions. |
| const Extension* extension = |
| content::Details<UnloadedExtensionInfo>(details)->extension; |
| - if (ContainsKey(context_items_, extension->id())) { |
| - RemoveAllContextItems(extension->id()); |
| + MenuItem::ExtensionKey extension_key(extension->id()); |
| + if (ContainsKey(context_items_, extension_key)) { |
| + RemoveAllContextItems(extension_key); |
| } |
| break; |
| } |
| @@ -859,18 +881,46 @@ void MenuManager::RemoveAllIncognitoContextItems() { |
| RemoveContextMenuItem(*remove_iter); |
| } |
| +MenuItem::ExtensionKey::ExtensionKey() : webview_instance_id(0) {} |
| + |
| +MenuItem::ExtensionKey::ExtensionKey(const std::string& extension_id, |
| + int webview_instance_id) |
| + : extension_id(extension_id), webview_instance_id(webview_instance_id) {} |
| + |
| +MenuItem::ExtensionKey::ExtensionKey(const std::string& extension_id) |
| + : extension_id(extension_id), webview_instance_id(0) {} |
| + |
| +bool MenuItem::ExtensionKey::operator==(const ExtensionKey& other) const { |
| + return extension_id == other.extension_id && |
| + webview_instance_id == other.webview_instance_id; |
| +} |
| + |
| +bool MenuItem::ExtensionKey::operator<(const ExtensionKey& other) const { |
| + if (webview_instance_id != other.webview_instance_id) |
| + return webview_instance_id < other.webview_instance_id; |
| + |
| + return extension_id < other.extension_id; |
| +} |
| + |
| +bool MenuItem::ExtensionKey::operator!=(const ExtensionKey& other) const { |
| + return !(*this == other); |
| +} |
| + |
| +bool MenuItem::ExtensionKey::empty() const { |
| + return extension_id.empty() && !webview_instance_id; |
| +} |
| + |
| MenuItem::Id::Id() : incognito(false), uid(0) {} |
| MenuItem::Id::Id(bool incognito, const std::string& extension_id) |
| - : incognito(incognito), extension_id(extension_id), uid(0) {} |
| + : incognito(incognito), extension_key(extension_id), uid(0) {} |
| MenuItem::Id::~Id() { |
| } |
| bool MenuItem::Id::operator==(const Id& other) const { |
| return (incognito == other.incognito && |
| - extension_id == other.extension_id && |
| - uid == other.uid && |
| + extension_key == other.extension_key && uid == other.uid && |
| string_uid == other.string_uid); |
| } |
| @@ -882,9 +932,9 @@ bool MenuItem::Id::operator<(const Id& other) const { |
| if (incognito < other.incognito) |
| return true; |
| if (incognito == other.incognito) { |
| - if (extension_id < other.extension_id) |
| + if (extension_key < other.extension_key) |
| return true; |
| - if (extension_id == other.extension_id) { |
| + if (extension_key == other.extension_key) { |
| if (uid < other.uid) |
| return true; |
| if (uid == other.uid) |