| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/extensions/extension.h" | 5 #include "chrome/common/extensions/extension.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 Extension::OAuth2Info::OAuth2Info() {} | 243 Extension::OAuth2Info::OAuth2Info() {} |
| 244 Extension::OAuth2Info::~OAuth2Info() {} | 244 Extension::OAuth2Info::~OAuth2Info() {} |
| 245 | 245 |
| 246 ExtensionOAuth2Scopes Extension::OAuth2Info::GetScopesAsSet() { | 246 ExtensionOAuth2Scopes Extension::OAuth2Info::GetScopesAsSet() { |
| 247 ExtensionOAuth2Scopes result; | 247 ExtensionOAuth2Scopes result; |
| 248 std::copy(scopes.begin(), scopes.end(), | 248 std::copy(scopes.begin(), scopes.end(), |
| 249 std::inserter(result, result.begin())); | 249 std::inserter(result, result.begin())); |
| 250 return result; | 250 return result; |
| 251 } | 251 } |
| 252 | 252 |
| 253 Extension::Command::Command() {} | |
| 254 Extension::Command::~Command() {} | |
| 255 | |
| 256 ui::Accelerator Extension::Command::ParseImpl( | |
| 257 const std::string& shortcut, | |
| 258 const std::string& platform_key, | |
| 259 int index, | |
| 260 string16* error) { | |
| 261 if (platform_key != values::kKeybindingPlatformWin && | |
| 262 platform_key != values::kKeybindingPlatformMac && | |
| 263 platform_key != values::kKeybindingPlatformChromeOs && | |
| 264 platform_key != values::kKeybindingPlatformLinux && | |
| 265 platform_key != values::kKeybindingPlatformDefault) { | |
| 266 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
| 267 errors::kInvalidKeyBindingUnknownPlatform, | |
| 268 base::IntToString(index), | |
| 269 platform_key); | |
| 270 return ui::Accelerator(); | |
| 271 } | |
| 272 | |
| 273 std::vector<std::string> tokens; | |
| 274 base::SplitString(shortcut, '+', &tokens); | |
| 275 if (tokens.size() < 2 || tokens.size() > 3) { | |
| 276 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
| 277 errors::kInvalidKeyBinding, | |
| 278 base::IntToString(index), | |
| 279 platform_key, | |
| 280 shortcut); | |
| 281 return ui::Accelerator(); | |
| 282 } | |
| 283 | |
| 284 // Now, parse it into an accelerator. | |
| 285 bool ctrl = false; | |
| 286 bool alt = false; | |
| 287 bool shift = false; | |
| 288 ui::KeyboardCode key = ui::VKEY_UNKNOWN; | |
| 289 for (size_t i = 0; i < tokens.size(); i++) { | |
| 290 if (tokens[i] == "Ctrl") { | |
| 291 ctrl = true; | |
| 292 } else if (tokens[i] == "Alt") { | |
| 293 alt = true; | |
| 294 } else if (tokens[i] == "Shift") { | |
| 295 shift = true; | |
| 296 } else if (tokens[i] == "Command" && platform_key == "mac") { | |
| 297 // TODO(finnur): Implement for Mac. | |
| 298 } else if (tokens[i] == "Option" && platform_key == "mac") { | |
| 299 // TODO(finnur): Implement for Mac. | |
| 300 } else if (tokens[i].size() == 1 && | |
| 301 tokens[i][0] >= 'A' && tokens[i][0] <= 'Z') { | |
| 302 if (key != ui::VKEY_UNKNOWN) { | |
| 303 // Multiple key assignments. | |
| 304 key = ui::VKEY_UNKNOWN; | |
| 305 break; | |
| 306 } | |
| 307 | |
| 308 key = static_cast<ui::KeyboardCode>(ui::VKEY_A + (tokens[i][0] - 'A')); | |
| 309 } else { | |
| 310 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
| 311 errors::kInvalidKeyBinding, | |
| 312 base::IntToString(index), | |
| 313 platform_key, | |
| 314 shortcut); | |
| 315 return ui::Accelerator(); | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 // We support Ctrl+foo, Alt+foo, Ctrl+Shift+foo, Alt+Shift+foo, but not | |
| 320 // Ctrl+Alt+foo. For a more detailed reason why we don't support Ctrl+Alt+foo: | |
| 321 // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx. | |
| 322 if (key == ui::VKEY_UNKNOWN || (ctrl && alt)) { | |
| 323 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
| 324 errors::kInvalidKeyBinding, | |
| 325 base::IntToString(index), | |
| 326 platform_key, | |
| 327 shortcut); | |
| 328 return ui::Accelerator(); | |
| 329 } | |
| 330 | |
| 331 return ui::Accelerator(key, shift, ctrl, alt); | |
| 332 } | |
| 333 | |
| 334 // static | |
| 335 std::string Extension::Command::CommandPlatform() { | |
| 336 #if defined(OS_WIN) | |
| 337 return values::kKeybindingPlatformWin; | |
| 338 #elif defined(OS_MACOSX) | |
| 339 return values::kKeybindingPlatformMac; | |
| 340 #elif defined(OS_CHROMEOS) | |
| 341 return values::kKeybindingPlatformChromeOs; | |
| 342 #elif defined(OS_LINUX) | |
| 343 return values::kKeybindingPlatformLinux; | |
| 344 #else | |
| 345 return ""; | |
| 346 #endif | |
| 347 } | |
| 348 | |
| 349 bool Extension::Command::Parse(DictionaryValue* command, | |
| 350 const std::string& command_name, | |
| 351 int index, | |
| 352 string16* error) { | |
| 353 DCHECK(!command_name.empty()); | |
| 354 | |
| 355 // We'll build up a map of platform-to-shortcut suggestions. | |
| 356 std::map<const std::string, std::string> suggestions; | |
| 357 | |
| 358 // First try to parse the |suggested_key| as a dictionary. | |
| 359 DictionaryValue* suggested_key_dict; | |
| 360 if (command->GetDictionary(keys::kSuggestedKey, &suggested_key_dict)) { | |
| 361 DictionaryValue::key_iterator iter = suggested_key_dict->begin_keys(); | |
| 362 for ( ; iter != suggested_key_dict->end_keys(); ++iter) { | |
| 363 // For each item in the dictionary, extract the platforms specified. | |
| 364 std::string suggested_key_string; | |
| 365 if (suggested_key_dict->GetString(*iter, &suggested_key_string) && | |
| 366 !suggested_key_string.empty()) { | |
| 367 // Found a platform, add it to the suggestions list. | |
| 368 suggestions[*iter] = suggested_key_string; | |
| 369 } else { | |
| 370 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
| 371 errors::kInvalidKeyBinding, | |
| 372 base::IntToString(index), | |
| 373 keys::kSuggestedKey, | |
| 374 "Missing"); | |
| 375 return false; | |
| 376 } | |
| 377 } | |
| 378 } else { | |
| 379 // No dictionary was found, fall back to using just a string, so developers | |
| 380 // don't have to specify a dictionary if they just want to use one default | |
| 381 // for all platforms. | |
| 382 std::string suggested_key_string; | |
| 383 if (command->GetString(keys::kSuggestedKey, &suggested_key_string) && | |
| 384 !suggested_key_string.empty()) { | |
| 385 // If only a signle string is provided, it must be default for all. | |
| 386 suggestions["default"] = suggested_key_string; | |
| 387 } else { | |
| 388 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
| 389 errors::kInvalidKeyBinding, | |
| 390 base::IntToString(index), | |
| 391 keys::kSuggestedKey, | |
| 392 "Missing"); | |
| 393 return false; | |
| 394 } | |
| 395 } | |
| 396 | |
| 397 std::string platform = CommandPlatform(); | |
| 398 std::string key = platform; | |
| 399 if (suggestions.find(key) == suggestions.end()) | |
| 400 key = values::kKeybindingPlatformDefault; | |
| 401 if (suggestions.find(key) == suggestions.end()) { | |
| 402 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
| 403 errors::kInvalidKeyBindingMissingPlatform, | |
| 404 base::IntToString(index), | |
| 405 keys::kSuggestedKey, | |
| 406 platform); | |
| 407 return false; // No platform specified and no fallback. Bail. | |
| 408 } | |
| 409 | |
| 410 // For developer convenience, we parse all the suggestions (and complain about | |
| 411 // errors for platforms other than the current one) but use only what we need. | |
| 412 std::map<const std::string, std::string>::const_iterator iter = | |
| 413 suggestions.begin(); | |
| 414 for ( ; iter != suggestions.end(); ++iter) { | |
| 415 // Note that we pass iter->first to pretend we are on a platform we're not | |
| 416 // on. | |
| 417 ui::Accelerator accelerator = | |
| 418 ParseImpl(iter->second, iter->first, index, error); | |
| 419 if (accelerator.key_code() == ui::VKEY_UNKNOWN) { | |
| 420 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
| 421 errors::kInvalidKeyBinding, | |
| 422 base::IntToString(index), | |
| 423 iter->first, | |
| 424 iter->second); | |
| 425 return false; | |
| 426 } | |
| 427 | |
| 428 if (iter->first == key) { | |
| 429 // This platform is our platform, so grab this key. | |
| 430 accelerator_ = accelerator; | |
| 431 command_name_ = command_name; | |
| 432 | |
| 433 if (command_name != | |
| 434 extension_manifest_values::kPageActionKeybindingEvent && | |
| 435 command_name != | |
| 436 extension_manifest_values::kBrowserActionKeybindingEvent) { | |
| 437 if (!command->GetString(keys::kDescription, &description_) || | |
| 438 description_.empty()) { | |
| 439 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | |
| 440 errors::kInvalidKeyBindingDescription, | |
| 441 base::IntToString(index)); | |
| 442 return false; | |
| 443 } | |
| 444 } | |
| 445 } | |
| 446 } | |
| 447 return true; | |
| 448 } | |
| 449 | |
| 450 // | 253 // |
| 451 // Extension | 254 // Extension |
| 452 // | 255 // |
| 453 | 256 |
| 454 // static | 257 // static |
| 455 scoped_refptr<Extension> Extension::Create(const FilePath& path, | 258 scoped_refptr<Extension> Extension::Create(const FilePath& path, |
| 456 Location location, | 259 Location location, |
| 457 const DictionaryValue& value, | 260 const DictionaryValue& value, |
| 458 int flags, | 261 int flags, |
| 459 std::string* utf8_error) { | 262 std::string* utf8_error) { |
| (...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1587 ++command_index; | 1390 ++command_index; |
| 1588 | 1391 |
| 1589 DictionaryValue* command = NULL; | 1392 DictionaryValue* command = NULL; |
| 1590 if (!commands->GetDictionary(*iter, &command)) { | 1393 if (!commands->GetDictionary(*iter, &command)) { |
| 1591 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( | 1394 *error = ExtensionErrorUtils::FormatErrorMessageUTF16( |
| 1592 errors::kInvalidKeyBindingDictionary, | 1395 errors::kInvalidKeyBindingDictionary, |
| 1593 base::IntToString(command_index)); | 1396 base::IntToString(command_index)); |
| 1594 return false; | 1397 return false; |
| 1595 } | 1398 } |
| 1596 | 1399 |
| 1597 scoped_ptr<Extension::Command> binding(new Command()); | 1400 scoped_ptr<extensions::Command> binding(new extensions::Command()); |
| 1598 if (!binding->Parse(command, *iter, command_index, error)) | 1401 if (!binding->Parse(command, *iter, command_index, error)) |
| 1599 return false; // |error| already set. | 1402 return false; // |error| already set. |
| 1600 | 1403 |
| 1601 std::string command_name = binding->command_name(); | 1404 std::string command_name = binding->command_name(); |
| 1602 if (command_name == values::kPageActionKeybindingEvent) { | 1405 if (command_name == values::kPageActionKeybindingEvent) { |
| 1603 page_action_command_.reset(binding.release()); | 1406 page_action_command_.reset(binding.release()); |
| 1604 } else if (command_name == values::kBrowserActionKeybindingEvent) { | 1407 } else if (command_name == values::kBrowserActionKeybindingEvent) { |
| 1605 browser_action_command_.reset(binding.release()); | 1408 browser_action_command_.reset(binding.release()); |
| 1606 } else { | 1409 } else { |
| 1607 if (command_name[0] != '_') // All commands w/underscore are reserved. | 1410 if (command_name[0] != '_') // All commands w/underscore are reserved. |
| (...skipping 2120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3728 already_disabled(false), | 3531 already_disabled(false), |
| 3729 extension(extension) {} | 3532 extension(extension) {} |
| 3730 | 3533 |
| 3731 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( | 3534 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( |
| 3732 const Extension* extension, | 3535 const Extension* extension, |
| 3733 const ExtensionPermissionSet* permissions, | 3536 const ExtensionPermissionSet* permissions, |
| 3734 Reason reason) | 3537 Reason reason) |
| 3735 : reason(reason), | 3538 : reason(reason), |
| 3736 extension(extension), | 3539 extension(extension), |
| 3737 permissions(permissions) {} | 3540 permissions(permissions) {} |
| OLD | NEW |