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/context_menus/context_menus_api.h"
6
7 #include <string>
8 #include <utility>
9
10 #include "base/strings/string_util.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/api/context_menus/context_menus_api_helpers.h"
13 #include "chrome/browser/extensions/menu_manager.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/extensions/api/context_menus.h"
16 #include "extensions/common/error_utils.h"
17 #include "extensions/common/manifest_handlers/background_info.h"
18 #include "extensions/common/url_pattern_set.h"
19
20 using extensions::ErrorUtils;
21
22 namespace {
23
24 const char kIdRequiredError[] =
25 "Extensions using event pages or Service "
26 "Workers must pass an id parameter to chrome.contextMenus.create";
27
28 } // namespace
29
30 namespace extensions {
31
Run()32 ExtensionFunction::ResponseAction ContextMenusCreateFunction::Run() {
33 MenuItem::Id id(browser_context()->IsOffTheRecord(),
34 MenuItem::ExtensionKey(extension_id()));
35 std::unique_ptr<api::context_menus::Create::Params> params(
36 api::context_menus::Create::Params::Create(*args_));
37 EXTENSION_FUNCTION_VALIDATE(params.get());
38
39 if (params->create_properties.id.get()) {
40 id.string_uid = *params->create_properties.id;
41 } else {
42 if (BackgroundInfo::HasLazyContext(extension()))
43 return RespondNow(Error(kIdRequiredError));
44
45 // The Generated Id is added by context_menus_custom_bindings.js.
46 base::DictionaryValue* properties = NULL;
47 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &properties));
48 EXTENSION_FUNCTION_VALIDATE(properties->GetInteger(
49 extensions::context_menus_api_helpers::kGeneratedIdKey, &id.uid));
50 }
51
52 std::string error;
53 if (!extensions::context_menus_api_helpers::CreateMenuItem(
54 params->create_properties, browser_context(), extension(), id,
55 &error)) {
56 return RespondNow(Error(std::move(error)));
57 }
58 return RespondNow(NoArguments());
59 }
60
Run()61 ExtensionFunction::ResponseAction ContextMenusUpdateFunction::Run() {
62 MenuItem::Id item_id(browser_context()->IsOffTheRecord(),
63 MenuItem::ExtensionKey(extension_id()));
64 std::unique_ptr<api::context_menus::Update::Params> params(
65 api::context_menus::Update::Params::Create(*args_));
66
67 EXTENSION_FUNCTION_VALIDATE(params.get());
68 if (params->id.as_string)
69 item_id.string_uid = *params->id.as_string;
70 else if (params->id.as_integer)
71 item_id.uid = *params->id.as_integer;
72 else
73 NOTREACHED();
74
75 std::string error;
76 if (!extensions::context_menus_api_helpers::UpdateMenuItem(
77 params->update_properties, browser_context(), extension(), item_id,
78 &error)) {
79 return RespondNow(Error(std::move(error)));
80 }
81 return RespondNow(NoArguments());
82 }
83
Run()84 ExtensionFunction::ResponseAction ContextMenusRemoveFunction::Run() {
85 std::unique_ptr<api::context_menus::Remove::Params> params(
86 api::context_menus::Remove::Params::Create(*args_));
87 EXTENSION_FUNCTION_VALIDATE(params.get());
88
89 MenuManager* manager = MenuManager::Get(browser_context());
90
91 MenuItem::Id id(browser_context()->IsOffTheRecord(),
92 MenuItem::ExtensionKey(extension_id()));
93 if (params->menu_item_id.as_string)
94 id.string_uid = *params->menu_item_id.as_string;
95 else if (params->menu_item_id.as_integer)
96 id.uid = *params->menu_item_id.as_integer;
97 else
98 NOTREACHED();
99
100 MenuItem* item = manager->GetItemById(id);
101 // Ensure one extension can't remove another's menu items.
102 if (!item || item->extension_id() != extension_id()) {
103 return RespondNow(
104 Error(extensions::context_menus_api_helpers::kCannotFindItemError,
105 extensions::context_menus_api_helpers::GetIDString(id)));
106 }
107
108 if (!manager->RemoveContextMenuItem(id))
109 return RespondNow(Error("Cannot remove menu item."));
110 manager->WriteToStorage(extension(), id.extension_key);
111 return RespondNow(NoArguments());
112 }
113
Run()114 ExtensionFunction::ResponseAction ContextMenusRemoveAllFunction::Run() {
115 MenuManager* manager = MenuManager::Get(browser_context());
116 manager->RemoveAllContextItems(MenuItem::ExtensionKey(extension()->id()));
117 manager->WriteToStorage(extension(),
118 MenuItem::ExtensionKey(extension()->id()));
119 return RespondNow(NoArguments());
120 }
121
122 } // namespace extensions
123