| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "webkit/plugins/npapi/plugin_list.h" | 5 #include "webkit/plugins/npapi/plugin_list.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 void PluginList::RegisterInternalPlugin(const FilePath& filename, | 223 void PluginList::RegisterInternalPlugin(const FilePath& filename, |
| 224 const std::string& name, | 224 const std::string& name, |
| 225 const std::string& description, | 225 const std::string& description, |
| 226 const std::string& mime_type_str, | 226 const std::string& mime_type_str, |
| 227 const PluginEntryPoints& entry_points) { | 227 const PluginEntryPoints& entry_points) { |
| 228 InternalPlugin plugin; | 228 InternalPlugin plugin; |
| 229 plugin.info.path = filename; | 229 plugin.info.path = filename; |
| 230 plugin.info.name = ASCIIToUTF16(name); | 230 plugin.info.name = ASCIIToUTF16(name); |
| 231 plugin.info.version = ASCIIToUTF16("1"); | 231 plugin.info.version = ASCIIToUTF16("1"); |
| 232 plugin.info.desc = ASCIIToUTF16(description); | 232 plugin.info.desc = ASCIIToUTF16(description); |
| 233 plugin.info.enabled = webkit::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED; | |
| 234 | 233 |
| 235 webkit::WebPluginMimeType mime_type; | 234 webkit::WebPluginMimeType mime_type; |
| 236 mime_type.mime_type = mime_type_str; | 235 mime_type.mime_type = mime_type_str; |
| 237 plugin.info.mime_types.push_back(mime_type); | 236 plugin.info.mime_types.push_back(mime_type); |
| 238 | 237 |
| 239 plugin.entry_points = entry_points; | 238 plugin.entry_points = entry_points; |
| 240 | 239 |
| 241 base::AutoLock lock(lock_); | 240 base::AutoLock lock(lock_); |
| 242 internal_plugins_.push_back(plugin); | 241 internal_plugins_.push_back(plugin); |
| 243 if (filename.value() == kDefaultPluginLibraryName) | 242 if (filename.value() == kDefaultPluginLibraryName) |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 if (!plugins_need_refresh_) | 400 if (!plugins_need_refresh_) |
| 402 return; | 401 return; |
| 403 } | 402 } |
| 404 | 403 |
| 405 ScopedVector<PluginGroup> new_plugin_groups; | 404 ScopedVector<PluginGroup> new_plugin_groups; |
| 406 AddHardcodedPluginGroups(&new_plugin_groups); | 405 AddHardcodedPluginGroups(&new_plugin_groups); |
| 407 // Do the actual loading of the plugins. | 406 // Do the actual loading of the plugins. |
| 408 LoadPluginsInternal(&new_plugin_groups); | 407 LoadPluginsInternal(&new_plugin_groups); |
| 409 | 408 |
| 410 base::AutoLock lock(lock_); | 409 base::AutoLock lock(lock_); |
| 411 // Grab all plugins that were found before to copy enabled statuses. | |
| 412 std::vector<webkit::WebPluginInfo> old_plugins; | |
| 413 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | |
| 414 const std::vector<webkit::WebPluginInfo>& gr_plugins = | |
| 415 plugin_groups_[i]->web_plugins_info(); | |
| 416 old_plugins.insert(old_plugins.end(), gr_plugins.begin(), gr_plugins.end()); | |
| 417 } | |
| 418 // Disable all of the plugins and plugin groups that are disabled by policy. | |
| 419 for (size_t i = 0; i < new_plugin_groups.size(); ++i) { | |
| 420 PluginGroup* group = new_plugin_groups[i]; | |
| 421 string16 group_name = group->GetGroupName(); | |
| 422 | |
| 423 std::vector<webkit::WebPluginInfo>& gr_plugins = | |
| 424 group->GetPluginsContainer(); | |
| 425 for (size_t j = 0; j < gr_plugins.size(); ++j) { | |
| 426 int plugin_found = -1; | |
| 427 for (size_t k = 0; k < old_plugins.size(); ++k) { | |
| 428 if (gr_plugins[j].path == old_plugins[k].path) { | |
| 429 plugin_found = k; | |
| 430 break; | |
| 431 } | |
| 432 } | |
| 433 if (plugin_found >= 0) | |
| 434 gr_plugins[j].enabled = old_plugins[plugin_found].enabled; | |
| 435 // Set the disabled flag of all plugins scheduled for disabling. | |
| 436 if (plugins_to_disable_.find(gr_plugins[j].path) != | |
| 437 plugins_to_disable_.end()) { | |
| 438 group->DisablePlugin(gr_plugins[j].path); | |
| 439 } | |
| 440 } | |
| 441 | |
| 442 if (group->IsEmpty()) { | |
| 443 new_plugin_groups.erase(new_plugin_groups.begin() + i); | |
| 444 --i; | |
| 445 continue; | |
| 446 } | |
| 447 | |
| 448 group->EnforceGroupPolicy(); | |
| 449 } | |
| 450 // We flush the list of prematurely disabled plugins after the load has | |
| 451 // finished. If for some reason a plugin reappears on a second load it is | |
| 452 // going to be loaded normally. This is only true for non-policy controlled | |
| 453 // plugins though. | |
| 454 plugins_to_disable_.clear(); | |
| 455 | |
| 456 plugin_groups_.swap(new_plugin_groups); | 410 plugin_groups_.swap(new_plugin_groups); |
| 457 } | 411 } |
| 458 | 412 |
| 459 void PluginList::LoadPlugin(const FilePath& path, | 413 void PluginList::LoadPlugin(const FilePath& path, |
| 460 ScopedVector<PluginGroup>* plugin_groups) { | 414 ScopedVector<PluginGroup>* plugin_groups) { |
| 461 LOG_IF(ERROR, PluginList::DebugPluginLoading()) | 415 LOG_IF(ERROR, PluginList::DebugPluginLoading()) |
| 462 << "Loading plugin " << path.value(); | 416 << "Loading plugin " << path.value(); |
| 463 WebPluginInfo plugin_info; | 417 WebPluginInfo plugin_info; |
| 464 const PluginEntryPoints* entry_points; | 418 const PluginEntryPoints* entry_points; |
| 465 | 419 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 486 | 440 |
| 487 base::AutoLock lock(lock_); | 441 base::AutoLock lock(lock_); |
| 488 AddToPluginGroups(plugin_info, plugin_groups); | 442 AddToPluginGroups(plugin_info, plugin_groups); |
| 489 } | 443 } |
| 490 | 444 |
| 491 void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) { | 445 void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) { |
| 492 LoadPlugins(); | 446 LoadPlugins(); |
| 493 base::AutoLock lock(lock_); | 447 base::AutoLock lock(lock_); |
| 494 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | 448 for (size_t i = 0; i < plugin_groups_.size(); ++i) { |
| 495 const std::vector<webkit::WebPluginInfo>& gr_plugins = | 449 const std::vector<webkit::WebPluginInfo>& gr_plugins = |
| 496 plugin_groups_[i]->web_plugins_info(); | 450 plugin_groups_[i]->web_plugin_infos(); |
| 497 plugins->insert(plugins->end(), gr_plugins.begin(), gr_plugins.end()); | 451 plugins->insert(plugins->end(), gr_plugins.begin(), gr_plugins.end()); |
| 498 } | 452 } |
| 499 } | 453 } |
| 500 | 454 |
| 501 void PluginList::GetPluginInfoArray( | 455 void PluginList::GetPluginInfoArray( |
| 502 const GURL& url, | 456 const GURL& url, |
| 503 const std::string& mime_type, | 457 const std::string& mime_type, |
| 504 bool allow_wildcard, | 458 bool allow_wildcard, |
| 505 bool* use_stale, | 459 bool* use_stale, |
| 506 std::vector<webkit::WebPluginInfo>* info, | 460 std::vector<webkit::WebPluginInfo>* info, |
| 507 std::vector<std::string>* actual_mime_types) { | 461 std::vector<std::string>* actual_mime_types) { |
| 508 DCHECK(mime_type == StringToLowerASCII(mime_type)); | 462 DCHECK(mime_type == StringToLowerASCII(mime_type)); |
| 509 DCHECK(info); | 463 DCHECK(info); |
| 510 | 464 |
| 511 if (!use_stale) | 465 if (!use_stale) |
| 512 LoadPlugins(); | 466 LoadPlugins(); |
| 513 base::AutoLock lock(lock_); | 467 base::AutoLock lock(lock_); |
| 514 if (use_stale) | 468 if (use_stale) |
| 515 *use_stale = plugins_need_refresh_; | 469 *use_stale = plugins_need_refresh_; |
| 516 info->clear(); | 470 info->clear(); |
| 517 if (actual_mime_types) | 471 if (actual_mime_types) |
| 518 actual_mime_types->clear(); | 472 actual_mime_types->clear(); |
| 519 | 473 |
| 520 std::set<FilePath> visited_plugins; | 474 std::set<FilePath> visited_plugins; |
| 521 | 475 |
| 522 // Add in plugins by mime type. | 476 // Add in plugins by mime type. |
| 523 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | 477 for (size_t i = 0; i < plugin_groups_.size(); ++i) { |
| 524 const std::vector<webkit::WebPluginInfo>& plugins = | 478 const std::vector<webkit::WebPluginInfo>& plugins = |
| 525 plugin_groups_[i]->web_plugins_info(); | 479 plugin_groups_[i]->web_plugin_infos(); |
| 526 for (size_t i = 0; i < plugins.size(); ++i) { | 480 for (size_t i = 0; i < plugins.size(); ++i) { |
| 527 if (SupportsType(plugins[i], mime_type, allow_wildcard)) { | 481 if (SupportsType(plugins[i], mime_type, allow_wildcard)) { |
| 528 FilePath path = plugins[i].path; | 482 FilePath path = plugins[i].path; |
| 529 if (path.value() != kDefaultPluginLibraryName && | 483 if (path.value() != kDefaultPluginLibraryName && |
| 530 visited_plugins.insert(path).second) { | 484 visited_plugins.insert(path).second) { |
| 531 info->push_back(plugins[i]); | 485 info->push_back(plugins[i]); |
| 532 if (actual_mime_types) | 486 if (actual_mime_types) |
| 533 actual_mime_types->push_back(mime_type); | 487 actual_mime_types->push_back(mime_type); |
| 534 } | 488 } |
| 535 } | 489 } |
| 536 } | 490 } |
| 537 } | 491 } |
| 538 | 492 |
| 539 // Add in plugins by url. | 493 // Add in plugins by url. |
| 540 std::string path = url.path(); | 494 std::string path = url.path(); |
| 541 std::string::size_type last_dot = path.rfind('.'); | 495 std::string::size_type last_dot = path.rfind('.'); |
| 542 if (last_dot != std::string::npos) { | 496 if (last_dot != std::string::npos) { |
| 543 std::string extension = StringToLowerASCII(std::string(path, last_dot+1)); | 497 std::string extension = StringToLowerASCII(std::string(path, last_dot+1)); |
| 544 std::string actual_mime_type; | 498 std::string actual_mime_type; |
| 545 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | 499 for (size_t i = 0; i < plugin_groups_.size(); ++i) { |
| 546 const std::vector<webkit::WebPluginInfo>& plugins = | 500 const std::vector<webkit::WebPluginInfo>& plugins = |
| 547 plugin_groups_[i]->web_plugins_info(); | 501 plugin_groups_[i]->web_plugin_infos(); |
| 548 for (size_t i = 0; i < plugins.size(); ++i) { | 502 for (size_t i = 0; i < plugins.size(); ++i) { |
| 549 if (SupportsExtension(plugins[i], extension, &actual_mime_type)) { | 503 if (SupportsExtension(plugins[i], extension, &actual_mime_type)) { |
| 550 FilePath path = plugins[i].path; | 504 FilePath path = plugins[i].path; |
| 551 if (path.value() != kDefaultPluginLibraryName && | 505 if (path.value() != kDefaultPluginLibraryName && |
| 552 visited_plugins.insert(path).second) { | 506 visited_plugins.insert(path).second) { |
| 553 info->push_back(plugins[i]); | 507 info->push_back(plugins[i]); |
| 554 if (actual_mime_types) | 508 if (actual_mime_types) |
| 555 actual_mime_types->push_back(actual_mime_type); | 509 actual_mime_types->push_back(actual_mime_type); |
| 556 } | 510 } |
| 557 } | 511 } |
| 558 } | 512 } |
| 559 } | 513 } |
| 560 } | 514 } |
| 561 | 515 |
| 562 // Add the default plugin at the end if it supports the mime type given, | 516 // Add the default plugin at the end if it supports the mime type given, |
| 563 // and the default plugin is enabled. | 517 // and the default plugin is enabled. |
| 564 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | 518 for (size_t i = 0; i < plugin_groups_.size(); ++i) { |
| 565 #if defined(OS_WIN) | 519 #if defined(OS_WIN) |
| 566 if (plugin_groups_[i]->identifier().compare( | 520 if (plugin_groups_[i]->identifier().compare( |
| 567 WideToUTF8(kDefaultPluginLibraryName)) == 0) { | 521 WideToUTF8(kDefaultPluginLibraryName)) == 0) { |
| 568 #else | 522 #else |
| 569 if (plugin_groups_[i]->identifier().compare( | 523 if (plugin_groups_[i]->identifier().compare( |
| 570 kDefaultPluginLibraryName) == 0) { | 524 kDefaultPluginLibraryName) == 0) { |
| 571 #endif | 525 #endif |
| 572 DCHECK_NE(0U, plugin_groups_[i]->web_plugins_info().size()); | 526 DCHECK_NE(0U, plugin_groups_[i]->web_plugin_infos().size()); |
| 573 const webkit::WebPluginInfo& default_info = | 527 const webkit::WebPluginInfo& default_info = |
| 574 plugin_groups_[i]->web_plugins_info()[0]; | 528 plugin_groups_[i]->web_plugin_infos()[0]; |
| 575 if (SupportsType(default_info, mime_type, allow_wildcard)) { | 529 if (SupportsType(default_info, mime_type, allow_wildcard)) { |
| 576 info->push_back(default_info); | 530 info->push_back(default_info); |
| 577 if (actual_mime_types) | 531 if (actual_mime_types) |
| 578 actual_mime_types->push_back(mime_type); | 532 actual_mime_types->push_back(mime_type); |
| 579 } | 533 } |
| 580 } | 534 } |
| 581 } | 535 } |
| 582 } | 536 } |
| 583 | 537 |
| 584 bool PluginList::GetPluginInfoByPath(const FilePath& plugin_path, | 538 bool PluginList::GetPluginInfoByPath(const FilePath& plugin_path, |
| 585 webkit::WebPluginInfo* info) { | 539 webkit::WebPluginInfo* info) { |
| 586 LoadPlugins(); | 540 LoadPlugins(); |
| 587 base::AutoLock lock(lock_); | 541 base::AutoLock lock(lock_); |
| 588 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | 542 for (size_t i = 0; i < plugin_groups_.size(); ++i) { |
| 589 const std::vector<webkit::WebPluginInfo>& plugins = | 543 const std::vector<webkit::WebPluginInfo>& plugins = |
| 590 plugin_groups_[i]->web_plugins_info(); | 544 plugin_groups_[i]->web_plugin_infos(); |
| 591 for (size_t i = 0; i < plugins.size(); ++i) { | 545 for (size_t i = 0; i < plugins.size(); ++i) { |
| 592 if (plugins[i].path == plugin_path) { | 546 if (plugins[i].path == plugin_path) { |
| 593 *info = plugins[i]; | 547 *info = plugins[i]; |
| 594 return true; | 548 return true; |
| 595 } | 549 } |
| 596 } | 550 } |
| 597 } | 551 } |
| 598 | 552 |
| 599 return false; | 553 return false; |
| 600 } | 554 } |
| 601 | 555 |
| 602 void PluginList::GetPluginGroups( | 556 void PluginList::GetPluginGroups( |
| 603 bool load_if_necessary, | 557 bool load_if_necessary, |
| 604 std::vector<PluginGroup>* plugin_groups) { | 558 std::vector<PluginGroup>* plugin_groups) { |
| 605 if (load_if_necessary) | 559 if (load_if_necessary) |
| 606 LoadPlugins(); | 560 LoadPlugins(); |
| 607 base::AutoLock lock(lock_); | 561 base::AutoLock lock(lock_); |
| 608 plugin_groups->clear(); | 562 plugin_groups->clear(); |
| 609 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | 563 for (size_t i = 0; i < plugin_groups_.size(); ++i) { |
| 610 // In some unit tests we can get confronted with empty groups but in real | 564 // In some unit tests we can get confronted with empty groups but in real |
| 611 // world code this if should never be false here. | 565 // world code this if should never be false here. |
| 612 if (!plugin_groups_[i]->IsEmpty()) | 566 if (!plugin_groups_[i]->IsEmpty()) |
| 613 plugin_groups->push_back(*plugin_groups_[i]); | 567 plugin_groups->push_back(*plugin_groups_[i]); |
| 614 } | 568 } |
| 615 } | 569 } |
| 616 | 570 |
| 617 const PluginGroup* PluginList::GetPluginGroup( | 571 PluginGroup* PluginList::GetPluginGroup( |
| 618 const webkit::WebPluginInfo& web_plugin_info) { | 572 const webkit::WebPluginInfo& web_plugin_info) { |
| 619 base::AutoLock lock(lock_); | 573 base::AutoLock lock(lock_); |
| 620 return AddToPluginGroups(web_plugin_info, &plugin_groups_); | 574 return new PluginGroup(*AddToPluginGroups(web_plugin_info, &plugin_groups_)); |
| 621 } | 575 } |
| 622 | 576 |
| 623 string16 PluginList::GetPluginGroupName(const std::string& identifier) { | 577 string16 PluginList::GetPluginGroupName(const std::string& identifier) { |
| 624 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | 578 for (size_t i = 0; i < plugin_groups_.size(); ++i) { |
| 625 if (plugin_groups_[i]->identifier() == identifier) | 579 if (plugin_groups_[i]->identifier() == identifier) |
| 626 return plugin_groups_[i]->GetGroupName(); | 580 return plugin_groups_[i]->GetGroupName(); |
| 627 } | 581 } |
| 628 return string16(); | 582 return string16(); |
| 629 } | 583 } |
| 630 | 584 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 // is not going to run anyway. | 617 // is not going to run anyway. |
| 664 for (size_t i = 0; i < plugin_groups->size(); ++i) { | 618 for (size_t i = 0; i < plugin_groups->size(); ++i) { |
| 665 if ((*plugin_groups)[i]->identifier() == identifier) { | 619 if ((*plugin_groups)[i]->identifier() == identifier) { |
| 666 group->set_identifier(PluginGroup::GetLongIdentifier(web_plugin_info)); | 620 group->set_identifier(PluginGroup::GetLongIdentifier(web_plugin_info)); |
| 667 break; | 621 break; |
| 668 } | 622 } |
| 669 } | 623 } |
| 670 plugin_groups->push_back(group); | 624 plugin_groups->push_back(group); |
| 671 } | 625 } |
| 672 group->AddPlugin(web_plugin_info); | 626 group->AddPlugin(web_plugin_info); |
| 673 // If group is scheduled for disabling do that now and remove it from the | |
| 674 // list. | |
| 675 if (groups_to_disable_.erase(group->GetGroupName())) | |
| 676 group->EnableGroup(false); | |
| 677 return group; | 627 return group; |
| 678 } | 628 } |
| 679 | 629 |
| 680 bool PluginList::EnablePlugin(const FilePath& filename) { | |
| 681 base::AutoLock lock(lock_); | |
| 682 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | |
| 683 if (plugin_groups_[i]->ContainsPlugin(filename)) | |
| 684 return plugin_groups_[i]->EnablePlugin(filename); | |
| 685 } | |
| 686 // Non existing plugin is being enabled. Check if it has been disabled before | |
| 687 // and remove it. | |
| 688 return (plugins_to_disable_.erase(filename) != 0); | |
| 689 } | |
| 690 | |
| 691 bool PluginList::DisablePlugin(const FilePath& filename) { | |
| 692 base::AutoLock lock(lock_); | |
| 693 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | |
| 694 if (plugin_groups_[i]->ContainsPlugin(filename)) | |
| 695 return plugin_groups_[i]->DisablePlugin(filename); | |
| 696 } | |
| 697 // Non existing plugin is being disabled. Queue the plugin so that on the next | |
| 698 // load plugins call they will be disabled. | |
| 699 plugins_to_disable_.insert(filename); | |
| 700 return true; | |
| 701 } | |
| 702 | |
| 703 bool PluginList::EnableGroup(bool enable, const string16& group_name) { | |
| 704 base::AutoLock lock(lock_); | |
| 705 PluginGroup* group = NULL; | |
| 706 for (size_t i = 0; i < plugin_groups_.size(); ++i) { | |
| 707 if (!plugin_groups_[i]->IsEmpty() && | |
| 708 plugin_groups_[i]->GetGroupName().find(group_name) != string16::npos) { | |
| 709 group = plugin_groups_[i]; | |
| 710 break; | |
| 711 } | |
| 712 } | |
| 713 if (!group) { | |
| 714 // Non existing group is being enabled. Queue the group so that on the next | |
| 715 // load plugins call they will be disabled. | |
| 716 if (!enable) { | |
| 717 groups_to_disable_.insert(group_name); | |
| 718 return true; | |
| 719 } else { | |
| 720 return (groups_to_disable_.erase(group_name) != 0); | |
| 721 } | |
| 722 } | |
| 723 | |
| 724 return group->EnableGroup(enable); | |
| 725 } | |
| 726 | |
| 727 bool PluginList::SupportsType(const webkit::WebPluginInfo& plugin, | 630 bool PluginList::SupportsType(const webkit::WebPluginInfo& plugin, |
| 728 const std::string& mime_type, | 631 const std::string& mime_type, |
| 729 bool allow_wildcard) { | 632 bool allow_wildcard) { |
| 730 // Webkit will ask for a plugin to handle empty mime types. | 633 // Webkit will ask for a plugin to handle empty mime types. |
| 731 if (mime_type.empty()) | 634 if (mime_type.empty()) |
| 732 return false; | 635 return false; |
| 733 | 636 |
| 734 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { | 637 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { |
| 735 const webkit::WebPluginMimeType& mime_info = plugin.mime_types[i]; | 638 const webkit::WebPluginMimeType& mime_info = plugin.mime_types[i]; |
| 736 if (net::MatchesMimeType(mime_info.mime_type, mime_type)) { | 639 if (net::MatchesMimeType(mime_info.mime_type, mime_type)) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 757 } | 660 } |
| 758 return false; | 661 return false; |
| 759 } | 662 } |
| 760 | 663 |
| 761 PluginList::~PluginList() { | 664 PluginList::~PluginList() { |
| 762 } | 665 } |
| 763 | 666 |
| 764 | 667 |
| 765 } // namespace npapi | 668 } // namespace npapi |
| 766 } // namespace webkit | 669 } // namespace webkit |
| OLD | NEW |