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

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: 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
15 namespace {
16
17 const char kExtension[] = "extension";
18 const char kCommandName[] = "command_name";
19
20 std::string GetPlatformKeybindingKeyForAccelerator(
21 const ui::Accelerator& accelerator) {
22 return Extension::ExtensionKeybinding::KeybindingPlatform() + ":" +
23 UTF16ToUTF8(accelerator.GetShortcutText());
24 }
25
26 } // namespace
27
28 // static
29 void ExtensionCommandService::RegisterUserPrefs(
30 PrefService* user_prefs) {
31 user_prefs->RegisterDictionaryPref(prefs::kExtensionKeybindings,
32 PrefService::SYNCABLE_PREF);
33 }
34
35 ExtensionCommandService::ExtensionCommandService(
36 Profile* profile)
37 : profile_(profile) {
38 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
39 content::Source<Profile>(profile->GetOriginalProfile()));
Yoyo Zhou 2012/05/01 01:51:30 Since it's redirected in incognito, the profile yo
40 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
41 content::Source<Profile>(profile->GetOriginalProfile()));
42 }
43
44 ExtensionCommandService::~ExtensionCommandService() {
45 }
46
47 const Extension::ExtensionKeybinding*
48 ExtensionCommandService::GetActiveBrowserActionCommand(
49 const std::string& extension_id) {
50 const Extension* extension =
51 profile_->GetExtensionService()->GetExtensionById(extension_id, false);
Yoyo Zhou 2012/05/01 01:51:30 Nit: eventually we'd like to get rid of GetExtensi
Finnur 2012/05/02 13:50:45 extensions() isn't defined in ExtensionSystem. We
Yoyo Zhou 2012/05/02 19:12:49 Eventually we'll want to deprecate profile_->GetEx
Finnur 2012/05/03 10:22:18 I see. Done!
52 CHECK(extension);
53 const Extension::ExtensionKeybinding* command =
54 extension->browser_action_command();
55 if (!command)
56 return NULL;
57 if (!IsKeybindingActive(command->accelerator(),
58 extension_id,
59 command->command_name())) {
60 return NULL;
61 }
62
63 return command;
64 }
65
66 const Extension::ExtensionKeybinding*
67 ExtensionCommandService::GetActivePageActionCommand(
68 const std::string& extension_id) {
69 const Extension* extension =
70 profile_->GetExtensionService()->GetExtensionById(extension_id, false);
71 CHECK(extension);
72 const Extension::ExtensionKeybinding* command =
73 extension->page_action_command();
74 if (!command)
75 return NULL;
76 if (!IsKeybindingActive(command->accelerator(),
77 extension_id,
78 command->command_name())) {
79 return NULL;
80 }
81
82 return command;
83 }
84
85 Extension::CommandMap ExtensionCommandService::GetActiveNamedCommands(
86 const std::string& extension_id) {
87 const Extension* extension =
88 profile_->GetExtensionService()->GetExtensionById(extension_id, false);
89 CHECK(extension);
90
91 Extension::CommandMap result;
92 const Extension::CommandMap& commands = extension->named_commands();
93 if (commands.empty())
94 return result;
95
96 Extension::CommandMap::const_iterator iter = commands.begin();
97 for (; iter != commands.end(); ++iter) {
98 if (!IsKeybindingActive(iter->second.accelerator(),
99 extension_id,
100 iter->second.command_name())) {
101 continue;
102 }
103
104 result[iter->second.command_name()] = iter->second;
105 }
106
107 return result;
108 }
109
110 bool ExtensionCommandService::IsKeybindingActive(
111 const ui::Accelerator& accelerator,
112 std::string extension_id,
113 std::string command_name) {
114 CHECK(!extension_id.empty());
115 CHECK(!command_name.empty());
116
117 std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator);
118 const DictionaryValue* bindings =
119 profile_->GetPrefs()->GetDictionary(prefs::kExtensionKeybindings);
120 if (!bindings->HasKey(key))
121 return false;
122
123 DictionaryValue* value = NULL;
124 if (!bindings->GetDictionary(key, &value) || !value)
Yoyo Zhou 2012/05/01 01:51:30 I don't think you need the extra null check.
125 return false;
126
127 std::string id;
128 if (!value->GetString(kExtension, &id) || id != extension_id)
129 return false; // Already taken by another extension.
Yoyo Zhou 2012/05/01 01:51:30 Comments are misleading. Actually it's "not taken
130
131 std::string command;
132 if (!value->GetString(kCommandName, &command) || command != command_name)
133 return false; // Already taken by another command.
134
135 return true; // We found a match, this one is active.
136 }
137
138 void ExtensionCommandService::AssignInitialKeybindings(
139 const Extension* extension) {
140 const Extension::CommandMap& commands = extension->named_commands();
141 Extension::CommandMap::const_iterator iter = commands.begin();
142 for (; iter != commands.end(); ++iter) {
143 AddKeybindingPref(iter->second.accelerator(),
144 extension->id(),
145 iter->second.command_name(),
Yoyo Zhou 2012/05/01 01:51:30 (sorry since I haven't seen the previous keybindin
Finnur 2012/05/02 13:50:45 No, but it cannot happen because command names are
146 false); // Overwriting not allowed.
147 }
148
149 const Extension::ExtensionKeybinding* browser_action_command =
150 extension->browser_action_command();
151 if (browser_action_command) {
152 AddKeybindingPref(browser_action_command->accelerator(),
153 extension->id(),
154 browser_action_command->command_name(),
155 false); // Overwriting not allowed.
156 }
157
158 const Extension::ExtensionKeybinding* page_action_command =
159 extension->page_action_command();
160 if (page_action_command) {
161 AddKeybindingPref(page_action_command->accelerator(),
162 extension->id(),
163 page_action_command->command_name(),
164 false); // Overwriting not allowed.
165 }
166 }
167
168 bool ExtensionCommandService::AddKeybindingPref(
169 const ui::Accelerator& accelerator,
170 std::string extension_id,
171 std::string command_name,
172 bool allow_overrides) {
173 DictionaryPrefUpdate updater(profile_->GetPrefs(),
174 prefs::kExtensionKeybindings);
175 DictionaryValue* bindings = updater.Get();
176
177 std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator);
178 if (bindings->HasKey(key) && !allow_overrides)
179 return false; // Already taken.
180
181 DictionaryValue* keybinding = new DictionaryValue();
182 keybinding->SetString(kExtension, extension_id);
183 keybinding->SetString(kCommandName, command_name);
184
185 bindings->Set(key, keybinding);
186 return true;
187 }
188
189 void ExtensionCommandService::Observe(
190 int type,
191 const content::NotificationSource& source,
192 const content::NotificationDetails& details) {
193 switch (type) {
194 case chrome::NOTIFICATION_EXTENSION_INSTALLED:
195 AssignInitialKeybindings(
196 content::Details<const Extension>(details).ptr());
197 break;
198 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
199 RemoveKeybindingPrefs(*content::Details<std::string>(details).ptr());
Finnur 2012/04/30 09:28:37 I made an error here earlier and discovered it whe
200 break;
201 default:
202 NOTREACHED();
203 break;
204 }
205 }
206
207 void ExtensionCommandService::RemoveKeybindingPrefs(std::string extension_id) {
208 DictionaryPrefUpdate updater(profile_->GetPrefs(),
209 prefs::kExtensionKeybindings);
210 DictionaryValue* bindings = updater.Get();
211
212 typedef std::vector<std::string> KeysToRemove;
213 KeysToRemove keys_to_remove;
214 for (DictionaryValue::key_iterator it = bindings->begin_keys();
215 it != bindings->end_keys(); ++it) {
216 std::string key = *it;
217 DictionaryValue* item = NULL;
218 bindings->GetDictionary(key, &item);
219
220 std::string extension;
221 item->GetString(kExtension, &extension);
222 if (extension == extension_id)
223 keys_to_remove.push_back(key);
224 }
225
226 for (KeysToRemove::const_iterator it = keys_to_remove.begin();
227 it != keys_to_remove.end(); ++it) {
228 bindings->Remove(*it, NULL);
229 }
230 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698