Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(399)

Side by Side Diff: chrome/browser/extensions/extension_command_service.cc

Issue 10201016: Conflict detection for Extension Keybinding. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Addressed comments Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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/extension_command_service.h"
6
7 #include "base/utf_string_conversions.h"
8 #include "chrome/browser/extensions/extension_keybinding_registry.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/prefs/scoped_user_pref_update.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/common/chrome_notification_types.h"
13 #include "chrome/common/pref_names.h"
14 #include "content/public/browser/notification_service.h"
15
16 namespace {
17
18 const char kExtension[] = "extension";
19 const char kCommandName[] = "command_name";
20
21 std::string GetPlatformKeybindingKeyForAccelerator(
22 const ui::Accelerator& accelerator) {
23 return Extension::ExtensionKeybinding::KeybindingPlatform() + ":" +
24 UTF16ToUTF8(accelerator.GetShortcutText());
25 }
26
27 } // namespace
28
29 // static
30 void ExtensionCommandService::RegisterUserPrefs(
31 PrefService* user_prefs) {
32 user_prefs->RegisterDictionaryPref(prefs::kExtensionKeybindings,
33 PrefService::SYNCABLE_PREF);
34 }
35
36 ExtensionCommandService::ExtensionCommandService(
37 Profile* profile)
38 : profile_(profile) {
39 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
40 content::Source<Profile>(profile));
41 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
42 content::Source<Profile>(profile));
43 }
44
45 ExtensionCommandService::~ExtensionCommandService() {
46 }
47
48 const Extension::ExtensionKeybinding*
49 ExtensionCommandService::GetActiveBrowserActionCommand(
50 const std::string& extension_id) {
51 const Extension* extension =
52 profile_->GetExtensionService()->GetExtensionById(extension_id, false);
53 CHECK(extension);
54 const Extension::ExtensionKeybinding* command =
55 extension->browser_action_command();
56 if (!command)
57 return NULL;
58 if (!IsKeybindingActive(command->accelerator(),
59 extension_id,
60 command->command_name())) {
61 return NULL;
62 }
63
64 return command;
65 }
66
67 const Extension::ExtensionKeybinding*
68 ExtensionCommandService::GetActivePageActionCommand(
69 const std::string& extension_id) {
70 const Extension* extension =
71 profile_->GetExtensionService()->GetExtensionById(extension_id, false);
72 CHECK(extension);
73 const Extension::ExtensionKeybinding* command =
74 extension->page_action_command();
75 if (!command)
76 return NULL;
77 if (!IsKeybindingActive(command->accelerator(),
78 extension_id,
79 command->command_name())) {
80 return NULL;
81 }
82
83 return command;
84 }
85
86 Extension::CommandMap ExtensionCommandService::GetActiveNamedCommands(
87 const std::string& extension_id) {
88 const Extension* extension =
89 profile_->GetExtensionService()->GetExtensionById(extension_id, false);
90 CHECK(extension);
91
92 Extension::CommandMap result;
93 const Extension::CommandMap& commands = extension->named_commands();
94 if (commands.empty())
95 return result;
96
97 Extension::CommandMap::const_iterator iter = commands.begin();
98 for (; iter != commands.end(); ++iter) {
99 if (!IsKeybindingActive(iter->second.accelerator(),
100 extension_id,
101 iter->second.command_name())) {
102 continue;
103 }
104
105 result[iter->second.command_name()] = iter->second;
106 }
107
108 return result;
109 }
110
111 bool ExtensionCommandService::IsKeybindingActive(
112 const ui::Accelerator& accelerator,
113 std::string extension_id,
114 std::string command_name) {
115 CHECK(!extension_id.empty());
116 CHECK(!command_name.empty());
117
118 std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator);
119 const DictionaryValue* bindings =
120 profile_->GetPrefs()->GetDictionary(prefs::kExtensionKeybindings);
121 if (!bindings->HasKey(key))
122 return false;
123
124 DictionaryValue* value = NULL;
125 if (!bindings->GetDictionary(key, &value))
126 return false;
127
128 std::string id;
129 if (!value->GetString(kExtension, &id) || id != extension_id)
130 return false; // Not active for this extension.
131
132 std::string command;
133 if (!value->GetString(kCommandName, &command) || command != command_name)
134 return false; // Not active for this command.
135
136 return true; // We found a match, this one is active.
137 }
138
139 bool ExtensionCommandService::AddKeybindingPref(
140 const ui::Accelerator& accelerator,
141 std::string extension_id,
142 std::string command_name,
143 bool allow_overrides) {
144 DictionaryPrefUpdate updater(profile_->GetPrefs(),
145 prefs::kExtensionKeybindings);
146 DictionaryValue* bindings = updater.Get();
147
148 std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator);
149 if (bindings->HasKey(key) && !allow_overrides)
150 return false; // Already taken.
151
152 DictionaryValue* keybinding = new DictionaryValue();
153 keybinding->SetString(kExtension, extension_id);
154 keybinding->SetString(kCommandName, command_name);
155
156 bindings->Set(key, keybinding);
157 return true;
158 }
159
160 void ExtensionCommandService::Observe(
161 int type,
162 const content::NotificationSource& source,
163 const content::NotificationDetails& details) {
164 switch (type) {
165 case chrome::NOTIFICATION_EXTENSION_INSTALLED:
166 AssignInitialKeybindings(
167 content::Details<const Extension>(details).ptr());
168 break;
169 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
170 RemoveKeybindingPrefs(*content::Details<std::string>(details).ptr());
171 break;
172 default:
173 NOTREACHED();
174 break;
175 }
176 }
177
178 void ExtensionCommandService::AssignInitialKeybindings(
179 const Extension* extension) {
180 const Extension::CommandMap& commands = extension->named_commands();
181 Extension::CommandMap::const_iterator iter = commands.begin();
182 for (; iter != commands.end(); ++iter) {
183 AddKeybindingPref(iter->second.accelerator(),
184 extension->id(),
185 iter->second.command_name(),
186 false); // Overwriting not allowed.
187 }
188
189 const Extension::ExtensionKeybinding* browser_action_command =
190 extension->browser_action_command();
191 if (browser_action_command) {
192 AddKeybindingPref(browser_action_command->accelerator(),
193 extension->id(),
194 browser_action_command->command_name(),
195 false); // Overwriting not allowed.
196 }
197
198 const Extension::ExtensionKeybinding* page_action_command =
199 extension->page_action_command();
200 if (page_action_command) {
201 AddKeybindingPref(page_action_command->accelerator(),
202 extension->id(),
203 page_action_command->command_name(),
204 false); // Overwriting not allowed.
205 }
206 }
207
208 void ExtensionCommandService::RemoveKeybindingPrefs(std::string extension_id) {
209 DictionaryPrefUpdate updater(profile_->GetPrefs(),
210 prefs::kExtensionKeybindings);
211 DictionaryValue* bindings = updater.Get();
212
213 typedef std::vector<std::string> KeysToRemove;
214 KeysToRemove keys_to_remove;
215 for (DictionaryValue::key_iterator it = bindings->begin_keys();
216 it != bindings->end_keys(); ++it) {
217 std::string key = *it;
218 DictionaryValue* item = NULL;
219 bindings->GetDictionary(key, &item);
220
221 std::string extension;
222 item->GetString(kExtension, &extension);
223 if (extension == extension_id)
224 keys_to_remove.push_back(key);
225 }
226
227 for (KeysToRemove::const_iterator it = keys_to_remove.begin();
228 it != keys_to_remove.end(); ++it) {
229 bindings->Remove(*it, NULL);
230 }
231 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_command_service.h ('k') | chrome/browser/extensions/extension_command_service_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698