| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2010 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/extension_context_menu_api.h" |
| 6 |
| 7 #include "chrome/browser/extensions/extension_menu_manager.h" |
| 8 #include "chrome/browser/extensions/extensions_service.h" |
| 9 #include "chrome/browser/profile.h" |
| 10 |
| 11 const wchar_t kEnabledContextsKey[] = L"enabledContexts"; |
| 12 const wchar_t kCheckedKey[] = L"checked"; |
| 13 const wchar_t kContextsKey[] = L"contexts"; |
| 14 const wchar_t kParentIdKey[] = L"parentId"; |
| 15 const wchar_t kTitleKey[] = L"title"; |
| 16 const wchar_t kTypeKey[] = L"type"; |
| 17 |
| 18 const char kTitleNeededError[] = |
| 19 "All menu items except for separators must have a title"; |
| 20 const char kCheckedError[] = |
| 21 "Only items with type RADIO or CHECKBOX can be checked"; |
| 22 const char kParentsMustBeNormalError[] = |
| 23 "Parent items must have type NORMAL"; |
| 24 |
| 25 bool ParseContexts(const DictionaryValue* properties, |
| 26 const std::wstring& key, |
| 27 ExtensionMenuItem::ContextList* result) { |
| 28 ListValue* list = NULL; |
| 29 if (!properties->GetList(key, &list)) { |
| 30 return true; |
| 31 } |
| 32 ExtensionMenuItem::ContextList tmp_result; |
| 33 |
| 34 std::string value; |
| 35 for (size_t i = 0; i < list->GetSize(); i++) { |
| 36 if (!list->GetString(i, &value)) |
| 37 return false; |
| 38 |
| 39 if (value == "ALL") |
| 40 tmp_result.Add(ExtensionMenuItem::ALL); |
| 41 else if (value == "PAGE") |
| 42 tmp_result.Add(ExtensionMenuItem::PAGE); |
| 43 else if (value == "SELECTION") |
| 44 tmp_result.Add(ExtensionMenuItem::SELECTION); |
| 45 else if (value == "LINK") |
| 46 tmp_result.Add(ExtensionMenuItem::LINK); |
| 47 else if (value == "EDITABLE") |
| 48 tmp_result.Add(ExtensionMenuItem::EDITABLE); |
| 49 else if (value == "IMAGE") |
| 50 tmp_result.Add(ExtensionMenuItem::IMAGE); |
| 51 else if (value == "VIDEO") |
| 52 tmp_result.Add(ExtensionMenuItem::VIDEO); |
| 53 else if (value == "AUDIO") |
| 54 tmp_result.Add(ExtensionMenuItem::AUDIO); |
| 55 else |
| 56 return false; |
| 57 } |
| 58 *result = tmp_result; |
| 59 return true; |
| 60 } |
| 61 |
| 62 bool CreateContextMenuFunction::RunImpl() { |
| 63 EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY)); |
| 64 const DictionaryValue* properties = args_as_dictionary(); |
| 65 std::string title; |
| 66 if (properties->HasKey(kTitleKey)) |
| 67 EXTENSION_FUNCTION_VALIDATE(properties->GetString(kTitleKey, &title)); |
| 68 |
| 69 ExtensionMenuManager* menu_manager = |
| 70 profile()->GetExtensionsService()->menu_manager(); |
| 71 |
| 72 ExtensionMenuItem::ContextList contexts(ExtensionMenuItem::PAGE); |
| 73 if (!ParseContexts(properties, kContextsKey, &contexts)) |
| 74 EXTENSION_FUNCTION_ERROR("Invalid value for " + WideToASCII(kContextsKey)); |
| 75 |
| 76 ExtensionMenuItem::ContextList enabled_contexts = contexts; |
| 77 if (!ParseContexts(properties, kEnabledContextsKey, &enabled_contexts)) |
| 78 EXTENSION_FUNCTION_ERROR("Invalid value for " + |
| 79 WideToASCII(kEnabledContextsKey)); |
| 80 |
| 81 ExtensionMenuItem::Type type = ExtensionMenuItem::NORMAL; |
| 82 if (properties->HasKey(kTypeKey)) { |
| 83 std::string type_string; |
| 84 EXTENSION_FUNCTION_VALIDATE(properties->GetString(kTypeKey, &type_string)); |
| 85 if (type_string == "CHECKBOX") |
| 86 type = ExtensionMenuItem::CHECKBOX; |
| 87 else if (type_string == "RADIO") |
| 88 type = ExtensionMenuItem::RADIO; |
| 89 else if (type_string == "SEPARATOR") |
| 90 type = ExtensionMenuItem::SEPARATOR; |
| 91 else if (type_string != "NORMAL") |
| 92 EXTENSION_FUNCTION_ERROR("Invalid type string '" + type_string + "'"); |
| 93 } |
| 94 |
| 95 if (title.empty() && type != ExtensionMenuItem::SEPARATOR) |
| 96 EXTENSION_FUNCTION_ERROR(kTitleNeededError); |
| 97 |
| 98 bool checked = false; |
| 99 if (properties->HasKey(kCheckedKey)) { |
| 100 EXTENSION_FUNCTION_VALIDATE(properties->GetBoolean(kCheckedKey, &checked)); |
| 101 if (checked && type != ExtensionMenuItem::CHECKBOX && |
| 102 type != ExtensionMenuItem::RADIO) |
| 103 EXTENSION_FUNCTION_ERROR(kCheckedError); |
| 104 } |
| 105 |
| 106 scoped_ptr<ExtensionMenuItem> item( |
| 107 new ExtensionMenuItem(extension_id(), title, checked, type, contexts, |
| 108 enabled_contexts)); |
| 109 |
| 110 int id = 0; |
| 111 if (properties->HasKey(kParentIdKey)) { |
| 112 int parent_id = 0; |
| 113 EXTENSION_FUNCTION_VALIDATE(properties->GetInteger(kParentIdKey, |
| 114 &parent_id)); |
| 115 ExtensionMenuItem* parent = menu_manager->GetItemById(parent_id); |
| 116 if (!parent) |
| 117 EXTENSION_FUNCTION_ERROR("Cannot find menu item with id " + |
| 118 IntToString(parent_id)); |
| 119 if (parent->type() != ExtensionMenuItem::NORMAL) |
| 120 EXTENSION_FUNCTION_ERROR(kParentsMustBeNormalError); |
| 121 |
| 122 id = menu_manager->AddChildItem(parent_id, item.release()); |
| 123 } else { |
| 124 id = menu_manager->AddContextItem(item.release()); |
| 125 } |
| 126 EXTENSION_FUNCTION_VALIDATE(id > 0); |
| 127 |
| 128 if (has_callback()) |
| 129 result_.reset(Value::CreateIntegerValue(id)); |
| 130 |
| 131 return true; |
| 132 } |
| 133 |
| 134 bool RemoveContextMenuFunction::RunImpl() { |
| 135 EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_INTEGER)); |
| 136 int id = 0; |
| 137 EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&id)); |
| 138 ExtensionsService* service = profile()->GetExtensionsService(); |
| 139 ExtensionMenuManager* manager = service->menu_manager(); |
| 140 |
| 141 ExtensionMenuItem* item = manager->GetItemById(id); |
| 142 // Ensure one extension can't remove another's menu items. |
| 143 if (!item || item->extension_id() != extension_id()) |
| 144 EXTENSION_FUNCTION_ERROR( |
| 145 StringPrintf("no menu item with id %d is registered", id)); |
| 146 |
| 147 EXTENSION_FUNCTION_VALIDATE(manager->RemoveContextMenuItem(id)); |
| 148 return true; |
| 149 } |
| OLD | NEW |