1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_context_menu_api.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h" 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h" 1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_error_utils.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kCheckedKey[] = "checked"; 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kContextsKey[] = "contexts"; 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kDocumentUrlPatternsKey[] = "documentUrlPatterns"; 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kGeneratedIdKey[] = "generatedId"; 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kParentIdKey[] = "parentId"; 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kTargetUrlPatternsKey[] = "targetUrlPatterns"; 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kTitleKey[] = "title"; 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kTypeKey[] = "type"; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kCannotFindItemError[] = "Cannot find menu item with id *"; 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kCheckedError[] = 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Only items with type \"radio\" or \"checkbox\" can be checked"; 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kInvalidURLPatternError[] = "Invalid url pattern '*'"; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kInvalidValueError[] = "Invalid value for *"; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kInvalidTypeStringError[] = "Invalid type string '*'"; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kParentsMustBeNormalError[] = 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Parent items must have type \"normal\""; 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kTitleNeededError[] = 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "All menu items except for separators must have a title"; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionContextMenuFunction::ParseContexts( 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& properties, 393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* key, 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem::ContextList* result) { 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* list = NULL; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!properties.GetList(key, &list)) { 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem::ContextList tmp_result; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string value; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < list->GetSize(); i++) { 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!list->GetString(i, &value)) 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (value == "all") { 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tmp_result.Add(ExtensionMenuItem::ALL); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (value == "page") { 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tmp_result.Add(ExtensionMenuItem::PAGE); 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (value == "selection") { 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tmp_result.Add(ExtensionMenuItem::SELECTION); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (value == "link") { 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tmp_result.Add(ExtensionMenuItem::LINK); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (value == "editable") { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tmp_result.Add(ExtensionMenuItem::EDITABLE); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (value == "image") { 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tmp_result.Add(ExtensionMenuItem::IMAGE); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (value == "video") { 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tmp_result.Add(ExtensionMenuItem::VIDEO); 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (value == "audio") { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tmp_result.Add(ExtensionMenuItem::AUDIO); 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (value == "frame") { 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tmp_result.Add(ExtensionMenuItem::FRAME); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick error_ = ExtensionErrorUtils::FormatErrorMessage(kInvalidValueError, key); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = tmp_result; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionContextMenuFunction::ParseType( 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& properties, 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ExtensionMenuItem::Type& default_value, 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem::Type* result) { 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(result); 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!properties.HasKey(kTypeKey)) { 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = default_value; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string type_string; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!properties.GetString(kTypeKey, &type_string)) 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type_string == "normal") { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = ExtensionMenuItem::NORMAL; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type_string == "checkbox") { 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = ExtensionMenuItem::CHECKBOX; 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type_string == "radio") { 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = ExtensionMenuItem::RADIO; 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type_string == "separator") { 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = ExtensionMenuItem::SEPARATOR; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage(kInvalidTypeStringError, 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch type_string); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionContextMenuFunction::ParseChecked( 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem::Type type, 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& properties, 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool default_value, 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* checked) { 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!properties.HasKey(kCheckedKey)) { 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *checked = default_value; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!properties.GetBoolean(kCheckedKey, checked)) 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (checked && type != ExtensionMenuItem::CHECKBOX && 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch type != ExtensionMenuItem::RADIO) { 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = kCheckedError; 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionContextMenuFunction::ParseURLPatterns( 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& properties, 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* key, 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionExtent* result) { 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!properties.HasKey(key)) 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* list = NULL; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!properties.GetList(key, &list)) 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (ListValue::iterator i = list->begin(); i != list->end(); ++i) { 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string tmp; 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(*i)->GetAsString(&tmp)) 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLPattern pattern(ExtensionMenuManager::kAllowedSchemes); 143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO(skerner): Consider enabling strict pattern parsing 144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // if this extension's location indicates that it is under development. 145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (URLPattern::PARSE_SUCCESS != pattern.Parse(tmp, 146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen URLPattern::PARSE_LENIENT)) { 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage(kInvalidURLPatternError, 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tmp); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->AddPattern(pattern); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionContextMenuFunction::SetURLPatterns( 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& properties, 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem* item) { 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Process the documentUrlPattern value. 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionExtent document_url_patterns; 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ParseURLPatterns(properties, kDocumentUrlPatternsKey, 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &document_url_patterns)) 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!document_url_patterns.is_empty()) { 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item->set_document_url_patterns(document_url_patterns); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Process the targetUrlPattern value. 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionExtent target_url_patterns; 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ParseURLPatterns(properties, kTargetUrlPatternsKey, 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &target_url_patterns)) 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!target_url_patterns.is_empty()) { 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item->set_target_url_patterns(target_url_patterns); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionContextMenuFunction::GetParent( 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& properties, 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ExtensionMenuManager& manager, 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem** result) { 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!properties.HasKey(kParentIdKey)) 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionMenuItem::Id parent_id(profile(), extension_id(), 0); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (properties.HasKey(kParentIdKey) && 190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch !properties.GetInteger(kParentIdKey, &parent_id.uid)) 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem* parent = manager.GetItemById(parent_id); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!parent) { 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick error_ = "Cannot find menu item with id " + 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::IntToString(parent_id.uid); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (parent->type() != ExtensionMenuItem::NORMAL) { 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = kParentsMustBeNormalError; 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = parent; 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CreateContextMenuFunction::RunImpl() { 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* properties; 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &properties)); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(properties != NULL); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 212513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionMenuItem::Id id(profile(), extension_id(), 0); 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(properties->GetInteger(kGeneratedIdKey, 214513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch &id.uid)); 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string title; 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (properties->HasKey(kTitleKey) && 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !properties->GetString(kTitleKey, &title)) 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuManager* menu_manager = 22121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen profile()->GetExtensionService()->menu_manager(); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem::ContextList contexts(ExtensionMenuItem::PAGE); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ParseContexts(*properties, kContextsKey, &contexts)) 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem::Type type; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ParseType(*properties, ExtensionMenuItem::NORMAL, &type)) 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (title.empty() && type != ExtensionMenuItem::SEPARATOR) { 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = kTitleNeededError; 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool checked; 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ParseChecked(type, *properties, false, &checked)) 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<ExtensionMenuItem> item( 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new ExtensionMenuItem(id, title, checked, type, contexts)); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!SetURLPatterns(*properties, item.get())) 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = true; 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (properties->HasKey(kParentIdKey)) { 248513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionMenuItem::Id parent_id(profile(), extension_id(), 0); 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(properties->GetInteger(kParentIdKey, 250513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch &parent_id.uid)); 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem* parent = menu_manager->GetItemById(parent_id); 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!parent) { 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 254513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch kCannotFindItemError, base::IntToString(parent_id.uid)); 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (parent->type() != ExtensionMenuItem::NORMAL) { 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = kParentsMustBeNormalError; 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = menu_manager->AddChildItem(parent_id, item.release()); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = menu_manager->AddContextItem(GetExtension(), item.release()); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!success) 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UpdateContextMenuFunction::RunImpl() { 273513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionMenuItem::Id item_id(profile(), extension_id(), 0); 274513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &item_id.uid)); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 27621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ExtensionService* service = profile()->GetExtensionService(); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuManager* manager = service->menu_manager(); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem* item = manager->GetItemById(item_id); 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!item || item->extension_id() != extension_id()) { 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 281513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch kCannotFindItemError, base::IntToString(item_id.uid)); 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue *properties = NULL; 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &properties)); 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(properties != NULL); 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuManager* menu_manager = 29021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen profile()->GetExtensionService()->menu_manager(); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Type. 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem::Type type; 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ParseType(*properties, item->type(), &type)) 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type != item->type()) 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item->set_type(type); 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Title. 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (properties->HasKey(kTitleKey)) { 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string title; 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(properties->GetString(kTitleKey, &title)); 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (title.empty() && type != ExtensionMenuItem::SEPARATOR) { 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = kTitleNeededError; 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item->set_title(title); 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Checked state. 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool checked; 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ParseChecked(item->type(), *properties, item->checked(), &checked)) 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (checked != item->checked()) { 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!item->SetChecked(checked)) 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Contexts. 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem::ContextList contexts(item->contexts()); 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ParseContexts(*properties, kContextsKey, &contexts)) 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contexts != item->contexts()) 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item->set_contexts(contexts); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Parent id. 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem* parent = NULL; 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetParent(*properties, *menu_manager, &parent)) 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (parent && !menu_manager->ChangeParent(item->id(), &parent->id())) 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!SetURLPatterns(*properties, item)) 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveContextMenuFunction::RunImpl() { 340513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionMenuItem::Id id(profile(), extension_id(), 0); 341513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &id.uid)); 34221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ExtensionService* service = profile()->GetExtensionService(); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuManager* manager = service->menu_manager(); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuItem* item = manager->GetItemById(id); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ensure one extension can't remove another's menu items. 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!item || item->extension_id() != extension_id()) { 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 349513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch kCannotFindItemError, base::IntToString(id.uid)); 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return manager->RemoveContextMenuItem(id); 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveAllContextMenusFunction::RunImpl() { 35721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ExtensionService* service = profile()->GetExtensionService(); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionMenuManager* manager = service->menu_manager(); 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch manager->RemoveAllContextItems(extension_id()); 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 362