Commit de0532a5 authored by Karan Bhatia's avatar Karan Bhatia Committed by Commit Bot

Extensions: Deprecate the plugins manifest key.

NPAPI plugin support has been removed from chrome and the plugins specified in
the "plugins" extension manifest key are not used currently. This CL removes the
manifest handler for the "plugins" key, the "plugins" manifest feature and
updates the public documentation. After this CL, loading an extension with the
plugins manifest key specified should cause an install warning.

BUG=732590
TEST=Load an unpacked extension which specifies a plugin as part of the
"plugins" manifest key. Ensure that an install warning is raised saying that the
"plugins" key is unrecognized.

Change-Id: Ic5aa4958af1257cb776508638e3c690fb6a57eb4
Reviewed-on: https://chromium-review.googlesource.com/783517
Commit-Queue: Karan Bhatia <karandeepb@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521538}
parent bfca05b3
...@@ -211,10 +211,10 @@ const char* const kSafeManifestEntries[] = { ...@@ -211,10 +211,10 @@ const char* const kSafeManifestEntries[] = {
// No constant in manifest_constants.cc. Declared as a feature, but unused. // No constant in manifest_constants.cc. Declared as a feature, but unused.
// "platforms", // "platforms",
// N/A on Chrome OS, so we don't care. // Deprecated manifest entry, so we don't care.
emk::kPlugins, "plugins",
// Stated 3D/WebGL/plugin requirements of an app. // Stated 3D/WebGL requirements of an app.
emk::kRequirements, emk::kRequirements,
// Execute some pages in a separate sandbox. (Note: Using string literal // Execute some pages in a separate sandbox. (Note: Using string literal
......
...@@ -207,10 +207,6 @@ ...@@ -207,10 +207,6 @@
"channel": "stable", "channel": "stable",
"extension_types": "all" "extension_types": "all"
}, },
"plugins": {
"channel": "stable",
"extension_types": ["extension", "legacy_packaged_app", "hosted_app"]
},
"requirements": { "requirements": {
"channel": "stable", "channel": "stable",
"extension_types": [ "extension_types": [
......
...@@ -113,10 +113,6 @@ and <a href="overview">Overview</a>. ...@@ -113,10 +113,6 @@ and <a href="overview">Overview</a>.
<td> <a href="permissions">Optional Permissions</a> </td> <td> <a href="permissions">Optional Permissions</a> </td>
<td> Modify your extension's permissions </td> <td> Modify your extension's permissions </td>
</tr> </tr>
<tr>
<td> <a href="npapi">NPAPI&nbsp;Plugins</a> </td>
<td> Load native binary code </td>
</tr>
<tr> <tr>
<td colspan="2"><h4>Finishing and distributing your extension</h4></td> <td colspan="2"><h4>Finishing and distributing your extension</h4></td>
......
...@@ -35,7 +35,6 @@ try the ...@@ -35,7 +35,6 @@ try the
<li><a href="#faq-dev-07">Can extensions encode/decode JSON data?</a></li> <li><a href="#faq-dev-07">Can extensions encode/decode JSON data?</a></li>
<li><a href="#faq-dev-08">Can extensions store data locally?</a></li> <li><a href="#faq-dev-08">Can extensions store data locally?</a></li>
<li><a href="#faq-dev-04">Can extensions use OAuth?</a></li> <li><a href="#faq-dev-04">Can extensions use OAuth?</a></li>
<li><a href="#faq-dev-06">Can extensions load DLLs?</a></li>
<li><a href="#faq-dev-05">Can extensions create UI outside of the rendered web page?</a></li> <li><a href="#faq-dev-05">Can extensions create UI outside of the rendered web page?</a></li>
<li><a href="#faq-interact-chrome">Can extensions listen to clicks on Chrome tabs and navigation buttons?</a> <li><a href="#faq-interact-chrome">Can extensions listen to clicks on Chrome tabs and navigation buttons?</a>
<li><a href="#faq-dev-11">Can two extensions communicate with each other?</a></li> <li><a href="#faq-dev-11">Can two extensions communicate with each other?</a></li>
...@@ -206,13 +205,6 @@ cros,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,#####</pre> ...@@ -206,13 +205,6 @@ cros,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,#####</pre>
in order to simplify the process of signing OAuth requests. in order to simplify the process of signing OAuth requests.
</p> </p>
<h3 id="faq-dev-06">Can extensions load DLLs?</h3>
<p>
Yes, using the <a href="npapi">NPAPI interface</a>.
Because of the possibility for abuse, though, we will review your extension
before hosting it in the Chrome Web Store.
</p>
<h3 id="faq-dev-05">Can extensions create UI outside of the rendered web page?</h3> <h3 id="faq-dev-05">Can extensions create UI outside of the rendered web page?</h3>
<p> <p>
Yes, your extension may add buttons to the Chrome browser's user interface. Yes, your extension may add buttons to the Chrome browser's user interface.
......
<h1>NPAPI Plugins</h1> <h1>NPAPI Plugins</h1>
<p class="warning">
NPAPI Plugin support for extension has been <a href="http://blog.chromium.org/2013/09/saying-goodbye-to-our-old-friend-npapi.html">discontinued</a>. The documentation below is preserved for historical purposes only.
</p>
<p> <p>
Leveraging HTML and JavaScript Leveraging HTML and JavaScript
makes developing new extensions really easy, makes developing new extensions really easy,
...@@ -11,9 +15,6 @@ allowing you to call into native binary code from JavaScript. ...@@ -11,9 +15,6 @@ allowing you to call into native binary code from JavaScript.
<h2 id="warning">Warning</h2> <h2 id="warning">Warning</h2>
<p align="center"><b><a href="http://blog.chromium.org/2013/09/saying-goodbye-to-our-old-friend-npapi.html">NPAPI is being phased out.</a>
Consider using alternatives.</b></p>
<p align="center"><b>NPAPI is a really big hammer that should only be used when no other approach will work.</b> <p align="center"><b>NPAPI is a really big hammer that should only be used when no other approach will work.</b>
<p>Code running in an NPAPI plugin has the full permissions of the current user and is not sandboxed or shielded from malicious input by Google Chrome in any way. You should be especially cautious when processing input from untrusted sources, such as when working with <p>Code running in an NPAPI plugin has the full permissions of the current user and is not sandboxed or shielded from malicious input by Google Chrome in any way. You should be especially cautious when processing input from untrusted sources, such as when working with
......
...@@ -185,10 +185,6 @@ ...@@ -185,10 +185,6 @@
"documentation": "declare_permissions", "documentation": "declare_permissions",
"example": ["tabs"] "example": ["tabs"]
}, },
"plugins": {
"documentation": "npapi",
"example": []
},
"requirements": { "requirements": {
"documentation": "manifest/requirements", "documentation": "manifest/requirements",
"example": {} "example": {}
......
...@@ -18,4 +18,10 @@ TEST_F(ChromeManifestTest, UnrecognizedKeyWarning) { ...@@ -18,4 +18,10 @@ TEST_F(ChromeManifestTest, UnrecognizedKeyWarning) {
"Unrecognized manifest key 'unrecognized_key_1'."); "Unrecognized manifest key 'unrecognized_key_1'.");
} }
// Tests that using the deprecated "plugins" key causes an install warning.
TEST_F(ChromeManifestTest, DeprecatedPluginsKey) {
LoadAndExpectWarning("deprecated_plugins_key.json",
"Unrecognized manifest key 'plugins'.");
}
} // namespace extensions } // namespace extensions
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/common/extensions/extension_test_util.h" #include "chrome/common/extensions/extension_test_util.h"
#include "components/crx_file/id_util.h" #include "components/crx_file/id_util.h"
#include "content/public/common/socket_permission_request.h" #include "content/public/common/socket_permission_request.h"
......
{
"name": "Deprecated plugins key.",
"version": "1.0",
"manifest_version": 2,
"plugins": [
{"path": "plugin.dll", "public": true}
]
}
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
"name": "Requirements Manifest Test", "name": "Requirements Manifest Test",
"version": "1.0", "version": "1.0",
"manifest_version": 2, "manifest_version": 2,
"plugins": [
{"path": "foo.dll", "public": true}
],
"requirements": { "requirements": {
"plugins": { "plugins": {
"npapi": false "npapi": false
......
...@@ -196,8 +196,6 @@ if (enable_extensions) { ...@@ -196,8 +196,6 @@ if (enable_extensions) {
"manifest_handlers/options_page_info.h", "manifest_handlers/options_page_info.h",
"manifest_handlers/permissions_parser.cc", "manifest_handlers/permissions_parser.cc",
"manifest_handlers/permissions_parser.h", "manifest_handlers/permissions_parser.h",
"manifest_handlers/plugins_handler.cc",
"manifest_handlers/plugins_handler.h",
"manifest_handlers/requirements_info.cc", "manifest_handlers/requirements_info.cc",
"manifest_handlers/requirements_info.h", "manifest_handlers/requirements_info.h",
"manifest_handlers/sandboxed_page_info.cc", "manifest_handlers/sandboxed_page_info.cc",
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "extensions/common/manifest_handlers/nacl_modules_handler.h" #include "extensions/common/manifest_handlers/nacl_modules_handler.h"
#include "extensions/common/manifest_handlers/oauth2_manifest_handler.h" #include "extensions/common/manifest_handlers/oauth2_manifest_handler.h"
#include "extensions/common/manifest_handlers/offline_enabled_info.h" #include "extensions/common/manifest_handlers/offline_enabled_info.h"
#include "extensions/common/manifest_handlers/plugins_handler.h"
#include "extensions/common/manifest_handlers/requirements_info.h" #include "extensions/common/manifest_handlers/requirements_info.h"
#include "extensions/common/manifest_handlers/sandboxed_page_info.h" #include "extensions/common/manifest_handlers/sandboxed_page_info.h"
#include "extensions/common/manifest_handlers/shared_module_info.h" #include "extensions/common/manifest_handlers/shared_module_info.h"
...@@ -63,7 +62,6 @@ void RegisterCommonManifestHandlers() { ...@@ -63,7 +62,6 @@ void RegisterCommonManifestHandlers() {
#endif #endif
(new OAuth2ManifestHandler)->Register(); (new OAuth2ManifestHandler)->Register();
(new OfflineEnabledHandler)->Register(); (new OfflineEnabledHandler)->Register();
(new PluginsHandler)->Register();
(new RequirementsHandler)->Register(); (new RequirementsHandler)->Register();
(new SandboxedPageHandler)->Register(); (new SandboxedPageHandler)->Register();
(new SharedModuleHandler)->Register(); (new SharedModuleHandler)->Register();
......
...@@ -130,9 +130,6 @@ const char kPlatformAppBackground[] = "app.background"; ...@@ -130,9 +130,6 @@ const char kPlatformAppBackground[] = "app.background";
const char kPlatformAppBackgroundPage[] = "app.background.page"; const char kPlatformAppBackgroundPage[] = "app.background.page";
const char kPlatformAppBackgroundScripts[] = "app.background.scripts"; const char kPlatformAppBackgroundScripts[] = "app.background.scripts";
const char kPlatformAppContentSecurityPolicy[] = "app.content_security_policy"; const char kPlatformAppContentSecurityPolicy[] = "app.content_security_policy";
const char kPlugins[] = "plugins";
const char kPluginsPath[] = "path";
const char kPluginsPublic[] = "public";
const char kPublicKey[] = "key"; const char kPublicKey[] = "key";
const char kRemoveButton[] = "remove_button"; const char kRemoveButton[] = "remove_button";
const char kRequirements[] = "requirements"; const char kRequirements[] = "requirements";
...@@ -603,12 +600,6 @@ const char kInvalidPermissions[] = ...@@ -603,12 +600,6 @@ const char kInvalidPermissions[] =
"Invalid value for 'permissions'."; "Invalid value for 'permissions'.";
const char kInvalidPermissionScheme[] = const char kInvalidPermissionScheme[] =
"Invalid scheme for 'permissions[*]'."; "Invalid scheme for 'permissions[*]'.";
const char kInvalidPlugins[] =
"Invalid value for 'plugins'.";
const char kInvalidPluginsPath[] =
"Invalid value for 'plugins[*].path'.";
const char kInvalidPluginsPublic[] =
"Invalid value for 'plugins[*].public'.";
const char kInvalidRequirement[] = const char kInvalidRequirement[] =
"Invalid value for requirement \"*\""; "Invalid value for requirement \"*\"";
const char kInvalidRequirements[] = const char kInvalidRequirements[] =
......
...@@ -133,9 +133,6 @@ extern const char kPlatformAppBackground[]; ...@@ -133,9 +133,6 @@ extern const char kPlatformAppBackground[];
extern const char kPlatformAppBackgroundPage[]; extern const char kPlatformAppBackgroundPage[];
extern const char kPlatformAppBackgroundScripts[]; extern const char kPlatformAppBackgroundScripts[];
extern const char kPlatformAppContentSecurityPolicy[]; extern const char kPlatformAppContentSecurityPolicy[];
extern const char kPlugins[];
extern const char kPluginsPath[];
extern const char kPluginsPublic[];
extern const char kPublicKey[]; extern const char kPublicKey[];
extern const char kRemoveButton[]; extern const char kRemoveButton[];
extern const char kRequirements[]; extern const char kRequirements[];
...@@ -427,9 +424,6 @@ extern const char kInvalidPermissionWithDetail[]; ...@@ -427,9 +424,6 @@ extern const char kInvalidPermissionWithDetail[];
extern const char kInvalidPermission[]; extern const char kInvalidPermission[];
extern const char kInvalidPermissions[]; extern const char kInvalidPermissions[];
extern const char kInvalidPermissionScheme[]; extern const char kInvalidPermissionScheme[];
extern const char kInvalidPlugins[];
extern const char kInvalidPluginsPath[];
extern const char kInvalidPluginsPublic[];
extern const char kInvalidRequirement[]; extern const char kInvalidRequirement[];
extern const char kInvalidRequirements[]; extern const char kInvalidRequirements[];
extern const char kInvalidRunAt[]; extern const char kInvalidRunAt[];
......
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/common/manifest_handlers/plugins_handler.h"
#include <stddef.h>
#include <memory>
#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/strings/grit/extensions_strings.h"
#include "ui/base/l10n/l10n_util.h"
namespace extensions {
namespace keys = manifest_keys;
namespace {
// An NPAPI plugin included in the extension.
struct PluginInfo {
typedef std::vector<PluginInfo> PluginVector;
PluginInfo(const base::FilePath& plugin_path, bool plugin_is_public);
~PluginInfo();
base::FilePath path; // Path to the plugin.
bool is_public; // False if only this extension can load this plugin.
// Return the plugins for a given |extensions|, or NULL if none exist.
static const PluginVector* GetPlugins(const Extension* extension);
// Return true if the given |extension| has plugins, and false otherwise.
static bool HasPlugins(const Extension* extension);
};
struct PluginManifestData : Extension::ManifestData {
// Optional list of NPAPI plugins and associated properties for an extension.
PluginInfo::PluginVector plugins;
};
PluginInfo::PluginInfo(const base::FilePath& plugin_path, bool plugin_is_public)
: path(plugin_path), is_public(plugin_is_public) {}
PluginInfo::~PluginInfo() {}
// static
const PluginInfo::PluginVector* PluginInfo::GetPlugins(
const Extension* extension) {
PluginManifestData* data = static_cast<PluginManifestData*>(
extension->GetManifestData(keys::kPlugins));
return data ? &data->plugins : NULL;
}
// static
bool PluginInfo::HasPlugins(const Extension* extension) {
PluginManifestData* data = static_cast<PluginManifestData*>(
extension->GetManifestData(keys::kPlugins));
return data && !data->plugins.empty() ? true : false;
}
} // namespace
PluginsHandler::PluginsHandler() {}
PluginsHandler::~PluginsHandler() {}
const std::vector<std::string> PluginsHandler::Keys() const {
return SingleKey(keys::kPlugins);
}
bool PluginsHandler::Parse(Extension* extension, base::string16* error) {
const base::ListValue* list_value = NULL;
if (!extension->manifest()->GetList(keys::kPlugins, &list_value)) {
*error = base::ASCIIToUTF16(manifest_errors::kInvalidPlugins);
return false;
}
std::unique_ptr<PluginManifestData> plugins_data(new PluginManifestData);
for (size_t i = 0; i < list_value->GetSize(); ++i) {
const base::DictionaryValue* plugin_value = NULL;
if (!list_value->GetDictionary(i, &plugin_value)) {
*error = base::ASCIIToUTF16(manifest_errors::kInvalidPlugins);
return false;
}
// Get plugins[i].path.
std::string path_str;
if (!plugin_value->GetString(keys::kPluginsPath, &path_str)) {
*error = ErrorUtils::FormatErrorMessageUTF16(
manifest_errors::kInvalidPluginsPath, base::NumberToString(i));
return false;
}
// Get plugins[i].content (optional).
bool is_public = false;
if (plugin_value->HasKey(keys::kPluginsPublic)) {
if (!plugin_value->GetBoolean(keys::kPluginsPublic, &is_public)) {
*error = ErrorUtils::FormatErrorMessageUTF16(
manifest_errors::kInvalidPluginsPublic, base::NumberToString(i));
return false;
}
}
// We don't allow extensions to load NPAPI plugins on Chrome OS, but still
// parse the entries to display consistent error messages. If the extension
// actually requires the plugins then LoadRequirements will prevent it
// loading.
#if defined(OS_CHROMEOS)
continue;
#endif // defined(OS_CHROMEOS).
plugins_data->plugins.push_back(PluginInfo(
extension->path().Append(base::FilePath::FromUTF8Unsafe(path_str)),
is_public));
}
if (!plugins_data->plugins.empty())
extension->SetManifestData(keys::kPlugins, std::move(plugins_data));
return true;
}
bool PluginsHandler::Validate(const Extension* extension,
std::string* error,
std::vector<InstallWarning>* warnings) const {
// Validate claimed plugin paths.
if (PluginInfo::HasPlugins(extension)) {
const PluginInfo::PluginVector* plugins =
PluginInfo::GetPlugins(extension);
CHECK(plugins);
for (std::vector<PluginInfo>::const_iterator plugin =
plugins->begin();
plugin != plugins->end(); ++plugin) {
if (!base::PathExists(plugin->path)) {
*error =
l10n_util::GetStringFUTF8(IDS_EXTENSION_LOAD_PLUGIN_PATH_FAILED,
plugin->path.LossyDisplayName());
return false;
}
}
}
return true;
}
} // namespace extensions
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_COMMON_MANIFEST_HANDLERS_PLUGINS_HANDLER_H_
#define EXTENSIONS_COMMON_MANIFEST_HANDLERS_PLUGINS_HANDLER_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handler.h"
namespace extensions {
// Parses the "plugins" manifest key.
class PluginsHandler : public ManifestHandler {
public:
PluginsHandler();
~PluginsHandler() override;
bool Parse(Extension* extension, base::string16* error) override;
bool Validate(const Extension* extension,
std::string* error,
std::vector<InstallWarning>* warnings) const override;
private:
const std::vector<std::string> Keys() const override;
DISALLOW_COPY_AND_ASSIGN(PluginsHandler);
};
} // namespace extensions
#endif // EXTENSIONS_COMMON_MANIFEST_HANDLERS_PLUGINS_HANDLER_H_
...@@ -163,9 +163,6 @@ ...@@ -163,9 +163,6 @@
<message name="IDS_EXTENSION_LOAD_OPTIONS_PAGE_FAILED" desc=""> <message name="IDS_EXTENSION_LOAD_OPTIONS_PAGE_FAILED" desc="">
Could not load options page '<ph name="OPTIONS_PAGE">$1<ex>page.html</ex></ph>'. Could not load options page '<ph name="OPTIONS_PAGE">$1<ex>page.html</ex></ph>'.
</message> </message>
<message name="IDS_EXTENSION_LOAD_PLUGIN_PATH_FAILED" desc="">
Could not load '<ph name="PLUGIN_PATH">$1<ex>/path/to/file</ex></ph>' for plugin.
</message>
<message name="IDS_EXTENSION_LOCALES_NO_DEFAULT_LOCALE_SPECIFIED" desc=""> <message name="IDS_EXTENSION_LOCALES_NO_DEFAULT_LOCALE_SPECIFIED" desc="">
Localization used, but default_locale wasn't specified in the manifest. Localization used, but default_locale wasn't specified in the manifest.
</message> </message>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment