OLD | NEW |
| (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/api/commands/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/extensions/extension_system.h" | |
11 #include "chrome/browser/prefs/scoped_user_pref_update.h" | |
12 #include "chrome/browser/profiles/profile.h" | |
13 #include "chrome/common/chrome_notification_types.h" | |
14 #include "chrome/common/pref_names.h" | |
15 #include "content/public/browser/notification_service.h" | |
16 | |
17 using extensions::Extension; | |
18 | |
19 namespace { | |
20 | |
21 const char kExtension[] = "extension"; | |
22 const char kCommandName[] = "command_name"; | |
23 | |
24 std::string GetPlatformKeybindingKeyForAccelerator( | |
25 const ui::Accelerator& accelerator) { | |
26 return extensions::Command::CommandPlatform() + ":" + | |
27 UTF16ToUTF8(accelerator.GetShortcutText()); | |
28 } | |
29 | |
30 } // namespace | |
31 | |
32 namespace extensions { | |
33 | |
34 // static | |
35 void ExtensionCommandService::RegisterUserPrefs( | |
36 PrefService* user_prefs) { | |
37 user_prefs->RegisterDictionaryPref(prefs::kExtensionKeybindings, | |
38 PrefService::SYNCABLE_PREF); | |
39 } | |
40 | |
41 ExtensionCommandService::ExtensionCommandService( | |
42 Profile* profile) | |
43 : profile_(profile) { | |
44 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, | |
45 content::Source<Profile>(profile)); | |
46 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, | |
47 content::Source<Profile>(profile)); | |
48 } | |
49 | |
50 ExtensionCommandService::~ExtensionCommandService() { | |
51 } | |
52 | |
53 const extensions::Command* | |
54 ExtensionCommandService::GetBrowserActionCommand( | |
55 const std::string& extension_id, QueryType type) { | |
56 const ExtensionSet* extensions = | |
57 ExtensionSystem::Get(profile_)->extension_service()->extensions(); | |
58 const Extension* extension = extensions->GetByID(extension_id); | |
59 CHECK(extension); | |
60 | |
61 const extensions::Command* command = extension->browser_action_command(); | |
62 if (!command) | |
63 return NULL; | |
64 if (type == ACTIVE_ONLY && | |
65 !IsKeybindingActive(command->accelerator(), | |
66 extension_id, | |
67 command->command_name())) { | |
68 return NULL; | |
69 } | |
70 | |
71 return command; | |
72 } | |
73 | |
74 const extensions::Command* ExtensionCommandService::GetPageActionCommand( | |
75 const std::string& extension_id, QueryType type) { | |
76 const ExtensionSet* extensions = | |
77 ExtensionSystem::Get(profile_)->extension_service()->extensions(); | |
78 const Extension* extension = extensions->GetByID(extension_id); | |
79 CHECK(extension); | |
80 | |
81 const extensions::Command* command = extension->page_action_command(); | |
82 if (!command) | |
83 return NULL; | |
84 if (type == ACTIVE_ONLY && | |
85 !IsKeybindingActive(command->accelerator(), | |
86 extension_id, | |
87 command->command_name())) { | |
88 return NULL; | |
89 } | |
90 | |
91 return command; | |
92 } | |
93 | |
94 extensions::CommandMap ExtensionCommandService::GetNamedCommands( | |
95 const std::string& extension_id, QueryType type) { | |
96 const ExtensionSet* extensions = | |
97 ExtensionSystem::Get(profile_)->extension_service()->extensions(); | |
98 const Extension* extension = extensions->GetByID(extension_id); | |
99 CHECK(extension); | |
100 | |
101 extensions::CommandMap result; | |
102 const extensions::CommandMap& commands = extension->named_commands(); | |
103 if (commands.empty()) | |
104 return result; | |
105 | |
106 extensions::CommandMap::const_iterator iter = commands.begin(); | |
107 for (; iter != commands.end(); ++iter) { | |
108 if (type == ACTIVE_ONLY && | |
109 !IsKeybindingActive(iter->second.accelerator(), | |
110 extension_id, | |
111 iter->second.command_name())) { | |
112 continue; | |
113 } | |
114 | |
115 result[iter->second.command_name()] = iter->second; | |
116 } | |
117 | |
118 return result; | |
119 } | |
120 | |
121 bool ExtensionCommandService::IsKeybindingActive( | |
122 const ui::Accelerator& accelerator, | |
123 const std::string& extension_id, | |
124 const std::string& command_name) const { | |
125 CHECK(!extension_id.empty()); | |
126 CHECK(!command_name.empty()); | |
127 | |
128 std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator); | |
129 const DictionaryValue* bindings = | |
130 profile_->GetPrefs()->GetDictionary(prefs::kExtensionKeybindings); | |
131 if (!bindings->HasKey(key)) | |
132 return false; | |
133 | |
134 DictionaryValue* value = NULL; | |
135 if (!bindings->GetDictionary(key, &value)) | |
136 return false; | |
137 | |
138 std::string id; | |
139 if (!value->GetString(kExtension, &id) || id != extension_id) | |
140 return false; // Not active for this extension. | |
141 | |
142 std::string command; | |
143 if (!value->GetString(kCommandName, &command) || command != command_name) | |
144 return false; // Not active for this command. | |
145 | |
146 return true; // We found a match, this one is active. | |
147 } | |
148 | |
149 bool ExtensionCommandService::AddKeybindingPref( | |
150 const ui::Accelerator& accelerator, | |
151 std::string extension_id, | |
152 std::string command_name, | |
153 bool allow_overrides) { | |
154 DictionaryPrefUpdate updater(profile_->GetPrefs(), | |
155 prefs::kExtensionKeybindings); | |
156 DictionaryValue* bindings = updater.Get(); | |
157 | |
158 std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator); | |
159 if (bindings->HasKey(key) && !allow_overrides) | |
160 return false; // Already taken. | |
161 | |
162 DictionaryValue* keybinding = new DictionaryValue(); | |
163 keybinding->SetString(kExtension, extension_id); | |
164 keybinding->SetString(kCommandName, command_name); | |
165 | |
166 bindings->Set(key, keybinding); | |
167 return true; | |
168 } | |
169 | |
170 void ExtensionCommandService::Observe( | |
171 int type, | |
172 const content::NotificationSource& source, | |
173 const content::NotificationDetails& details) { | |
174 switch (type) { | |
175 case chrome::NOTIFICATION_EXTENSION_INSTALLED: | |
176 AssignInitialKeybindings( | |
177 content::Details<const Extension>(details).ptr()); | |
178 break; | |
179 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: | |
180 RemoveKeybindingPrefs(*content::Details<std::string>(details).ptr()); | |
181 break; | |
182 default: | |
183 NOTREACHED(); | |
184 break; | |
185 } | |
186 } | |
187 | |
188 void ExtensionCommandService::AssignInitialKeybindings( | |
189 const Extension* extension) { | |
190 const extensions::CommandMap& commands = extension->named_commands(); | |
191 extensions::CommandMap::const_iterator iter = commands.begin(); | |
192 for (; iter != commands.end(); ++iter) { | |
193 AddKeybindingPref(iter->second.accelerator(), | |
194 extension->id(), | |
195 iter->second.command_name(), | |
196 false); // Overwriting not allowed. | |
197 } | |
198 | |
199 const extensions::Command* browser_action_command = | |
200 extension->browser_action_command(); | |
201 if (browser_action_command) { | |
202 AddKeybindingPref(browser_action_command->accelerator(), | |
203 extension->id(), | |
204 browser_action_command->command_name(), | |
205 false); // Overwriting not allowed. | |
206 } | |
207 | |
208 const extensions::Command* page_action_command = | |
209 extension->page_action_command(); | |
210 if (page_action_command) { | |
211 AddKeybindingPref(page_action_command->accelerator(), | |
212 extension->id(), | |
213 page_action_command->command_name(), | |
214 false); // Overwriting not allowed. | |
215 } | |
216 } | |
217 | |
218 void ExtensionCommandService::RemoveKeybindingPrefs(std::string extension_id) { | |
219 DictionaryPrefUpdate updater(profile_->GetPrefs(), | |
220 prefs::kExtensionKeybindings); | |
221 DictionaryValue* bindings = updater.Get(); | |
222 | |
223 typedef std::vector<std::string> KeysToRemove; | |
224 KeysToRemove keys_to_remove; | |
225 for (DictionaryValue::key_iterator it = bindings->begin_keys(); | |
226 it != bindings->end_keys(); ++it) { | |
227 std::string key = *it; | |
228 DictionaryValue* item = NULL; | |
229 bindings->GetDictionary(key, &item); | |
230 | |
231 std::string extension; | |
232 item->GetString(kExtension, &extension); | |
233 if (extension == extension_id) | |
234 keys_to_remove.push_back(key); | |
235 } | |
236 | |
237 for (KeysToRemove::const_iterator it = keys_to_remove.begin(); | |
238 it != keys_to_remove.end(); ++it) { | |
239 bindings->Remove(*it, NULL); | |
240 } | |
241 } | |
242 | |
243 } // namespace extensions | |
OLD | NEW |