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