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

Extensions: Deprecate the plugins requirement.

NPAPI plugin support has been removed from chrome and the "plugins" extension
manifest key is effectively deprecated. This CL deprecates the plugins
requirement. Extensions which specify the plugins requirements will now get an
install warning. Extensions explicitly requesting the npapi requirement (by
setting requirements.plugins.npapi to true) in their manifest will get a load
error.

BUG=732590

Change-Id: I874ca17b5143516f1746fff90197243eb6ac2999
Reviewed-on: https://chromium-review.googlesource.com/795361Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Commit-Queue: Karan Bhatia <karandeepb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521122}
parent 871e1bd9
...@@ -28,6 +28,10 @@ as demonstrated in the following example: ...@@ -28,6 +28,10 @@ as demonstrated in the following example:
} }
</pre> </pre>
<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>. As part of this, the <b>"plugins"</b> requirement described below has been deprecated.
</p>
<p> <p>
The "plugins" requirement indicates The "plugins" requirement indicates
if an app or extension requires NPAPI to run. if an app or extension requires NPAPI to run.
......
...@@ -33,15 +33,6 @@ TEST_F(RequirementsManifestTest, RequirementsInvalid) { ...@@ -33,15 +33,6 @@ TEST_F(RequirementsManifestTest, RequirementsInvalid) {
Testcase("requirements_invalid_3d_no_features.json", Testcase("requirements_invalid_3d_no_features.json",
ErrorUtils::FormatErrorMessage( ErrorUtils::FormatErrorMessage(
errors::kInvalidRequirement, "3D")), errors::kInvalidRequirement, "3D")),
Testcase("requirements_invalid_plugins.json",
ErrorUtils::FormatErrorMessage(
errors::kInvalidRequirement, "plugins")),
Testcase("requirements_invalid_plugins_key.json",
ErrorUtils::FormatErrorMessage(
errors::kInvalidRequirement, "plugins")),
Testcase("requirements_invalid_plugins_value.json",
ErrorUtils::FormatErrorMessage(
errors::kInvalidRequirement, "plugins"))
}; };
RunTestcases(testcases, arraysize(testcases), EXPECT_TYPE_ERROR); RunTestcases(testcases, arraysize(testcases), EXPECT_TYPE_ERROR);
...@@ -53,39 +44,27 @@ TEST_F(RequirementsManifestTest, RequirementsValid) { ...@@ -53,39 +44,27 @@ TEST_F(RequirementsManifestTest, RequirementsValid) {
"requirements_valid_empty.json")); "requirements_valid_empty.json"));
ASSERT_TRUE(extension.get()); ASSERT_TRUE(extension.get());
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).webgl, false); EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).webgl, false);
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).npapi, false);
// Test loading all the requirements. // Test loading all the requirements.
extension = LoadAndExpectSuccess("requirements_valid_full.json"); extension = LoadAndExpectSuccess("requirements_valid_full.json");
ASSERT_TRUE(extension.get()); ASSERT_TRUE(extension.get());
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).webgl, true); EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).webgl, true);
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).npapi, true);
} }
// When an npapi plugin is present, the default of the "npapi" requirement // Tests the deprecated plugin requirement.
// changes. TEST_F(RequirementsManifestTest, RequirementsPlugin) {
TEST_F(RequirementsManifestTest, RequirementsNpapiDefault) { // Using the plugins requirement should cause an install warning.
scoped_refptr<Extension> extension(LoadAndExpectSuccess( RunTestcase({"requirements_invalid_plugins_value.json",
"requirements_npapi_empty.json")); errors::kPluginsRequirementDeprecated},
ASSERT_TRUE(extension.get()); EXPECT_TYPE_WARNING);
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).webgl, false); RunTestcase(
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).npapi, true); {"requirements_npapi_false.json", errors::kPluginsRequirementDeprecated},
EXPECT_TYPE_WARNING);
extension = LoadAndExpectSuccess(
"requirements_npapi_empty_plugins_empty.json");
ASSERT_TRUE(extension.get());
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).webgl, false);
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).npapi, false);
extension = LoadAndExpectSuccess("requirements_npapi.json"); // Explicitly requesting the npapi requirement should cause an error.
ASSERT_TRUE(extension.get()); RunTestcase(
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).webgl, false); {"requirements_npapi_true.json", errors::kNPAPIPluginsNotSupported},
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).npapi, false); EXPECT_TYPE_ERROR);
extension = LoadAndExpectSuccess("requirements_npapi_plugins_empty.json");
ASSERT_TRUE(extension.get());
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).webgl, false);
EXPECT_EQ(RequirementsInfo::GetRequirements(extension.get()).npapi, true);
} }
} // namespace extensions } // namespace extensions
...@@ -11,13 +11,5 @@ ...@@ -11,13 +11,5 @@
"js": ["content_script.js"], "js": ["content_script.js"],
"run_at": "document_start" "run_at": "document_start"
}], }],
"permissions": [ "<all_urls>" ], "permissions": [ "<all_urls>" ]
"plugins": [
{"path": "plugin.dll", "public": true}
],
"requirements": {
"plugins": {
"npapi": false
}
}
} }
{
"name": "Requirements Manifest Test",
"version": "1.0",
"manifest_version": 2,
"requirements": {
"plugins": false
}
}
{
"name": "Requirements Manifest Test",
"version": "1.0",
"manifest_version": 2,
"requirements": {
"plugins": {
"foo": false
}
}
}
{
"name": "Requirements Manifest Test",
"version": "1.0",
"manifest_version": 2,
"plugins": [
{"path": "foo.dll", "public": true}
]
}
{
"name": "Requirements Manifest Test",
"version": "1.0",
"manifest_version": 2,
"plugins": [
]
}
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
"requirements": { "requirements": {
"3D": { "3D": {
"features": ["css3d", "webgl"] "features": ["css3d", "webgl"]
},
"plugins": {
"npapi": true
} }
} }
} }
...@@ -27,7 +27,6 @@ class PreloadCheck { ...@@ -27,7 +27,6 @@ class PreloadCheck {
BLACKLISTED_ID, BLACKLISTED_ID,
BLACKLISTED_UNKNOWN, BLACKLISTED_UNKNOWN,
DISALLOWED_BY_POLICY, DISALLOWED_BY_POLICY,
NPAPI_NOT_SUPPORTED,
WEBGL_NOT_SUPPORTED, WEBGL_NOT_SUPPORTED,
WINDOW_SHAPE_NOT_SUPPORTED, WINDOW_SHAPE_NOT_SUPPORTED,
}; };
......
...@@ -30,11 +30,6 @@ void RequirementsChecker::Start(ResultCallback callback) { ...@@ -30,11 +30,6 @@ void RequirementsChecker::Start(ResultCallback callback) {
const RequirementsInfo& requirements = const RequirementsInfo& requirements =
RequirementsInfo::GetRequirements(extension()); RequirementsInfo::GetRequirements(extension());
#if defined(OS_POSIX) && !defined(OS_MACOSX)
if (requirements.npapi)
errors_.insert(NPAPI_NOT_SUPPORTED);
#endif
#if !defined(USE_AURA) #if !defined(USE_AURA)
if (requirements.window_shape) if (requirements.window_shape)
errors_.insert(WINDOW_SHAPE_NOT_SUPPORTED); errors_.insert(WINDOW_SHAPE_NOT_SUPPORTED);
...@@ -55,12 +50,6 @@ void RequirementsChecker::Start(ResultCallback callback) { ...@@ -55,12 +50,6 @@ void RequirementsChecker::Start(ResultCallback callback) {
base::string16 RequirementsChecker::GetErrorMessage() const { base::string16 RequirementsChecker::GetErrorMessage() const {
// Join the error messages into one string. // Join the error messages into one string.
std::vector<std::string> messages; std::vector<std::string> messages;
#if defined(OS_POSIX) && !defined(OS_MACOSX)
if (errors_.count(NPAPI_NOT_SUPPORTED)) {
messages.push_back(
l10n_util::GetStringUTF8(IDS_EXTENSION_NPAPI_NOT_SUPPORTED));
}
#endif
if (errors_.count(WEBGL_NOT_SUPPORTED)) { if (errors_.count(WEBGL_NOT_SUPPORTED)) {
messages.push_back( messages.push_back(
l10n_util::GetStringUTF8(IDS_EXTENSION_WEBGL_NOT_SUPPORTED)); l10n_util::GetStringUTF8(IDS_EXTENSION_WEBGL_NOT_SUPPORTED));
......
...@@ -36,14 +36,6 @@ const bool kSupportsWindowShape = ...@@ -36,14 +36,6 @@ const bool kSupportsWindowShape =
false; false;
#endif #endif
// Whether this build supports the plugins.npapi requirement.
const bool kSupportsNPAPI =
#if defined(OS_POSIX) && !defined(OS_MACOSX)
false;
#else
true;
#endif
// Returns true if a WebGL check might not fail immediately. // Returns true if a WebGL check might not fail immediately.
bool MightSupportWebGL() { bool MightSupportWebGL() {
return content::GpuDataManager::GetInstance()->GpuAccessAllowed(nullptr); return content::GpuDataManager::GetInstance()->GpuAccessAllowed(nullptr);
...@@ -87,10 +79,6 @@ class RequirementsCheckerTest : public ExtensionsTest { ...@@ -87,10 +79,6 @@ class RequirementsCheckerTest : public ExtensionsTest {
manifest_dict_->SetBoolean("requirements.window.shape", true); manifest_dict_->SetBoolean("requirements.window.shape", true);
} }
void RequireNPAPI() {
manifest_dict_->SetBoolean("requirements.plugins.npapi", true);
}
void RequireFeature(const char feature[]) { void RequireFeature(const char feature[]) {
if (!manifest_dict_->HasKey(kFeaturesKey)) if (!manifest_dict_->HasKey(kFeaturesKey))
manifest_dict_->Set(kFeaturesKey, std::make_unique<base::ListValue>()); manifest_dict_->Set(kFeaturesKey, std::make_unique<base::ListValue>());
...@@ -120,8 +108,7 @@ TEST_F(RequirementsCheckerTest, RequirementsEmpty) { ...@@ -120,8 +108,7 @@ TEST_F(RequirementsCheckerTest, RequirementsEmpty) {
TEST_F(RequirementsCheckerTest, RequirementsSuccess) { TEST_F(RequirementsCheckerTest, RequirementsSuccess) {
if (kSupportsWindowShape) if (kSupportsWindowShape)
RequireWindowShape(); RequireWindowShape();
if (kSupportsNPAPI)
RequireNPAPI();
RequireFeature(kFeatureCSS3d); RequireFeature(kFeatureCSS3d);
CreateExtension(); CreateExtension();
...@@ -138,10 +125,6 @@ TEST_F(RequirementsCheckerTest, RequirementsFailMultiple) { ...@@ -138,10 +125,6 @@ TEST_F(RequirementsCheckerTest, RequirementsFailMultiple) {
RequireWindowShape(); RequireWindowShape();
expected_errors++; expected_errors++;
} }
if (!kSupportsNPAPI) {
RequireNPAPI();
expected_errors++;
}
if (!MightSupportWebGL()) { if (!MightSupportWebGL()) {
RequireFeature(kFeatureWebGL); RequireFeature(kFeatureWebGL);
expected_errors++; expected_errors++;
......
...@@ -64,7 +64,7 @@ void RegisterCommonManifestHandlers() { ...@@ -64,7 +64,7 @@ void RegisterCommonManifestHandlers() {
(new OAuth2ManifestHandler)->Register(); (new OAuth2ManifestHandler)->Register();
(new OfflineEnabledHandler)->Register(); (new OfflineEnabledHandler)->Register();
(new PluginsHandler)->Register(); (new PluginsHandler)->Register();
(new RequirementsHandler)->Register(); // Depends on plugins. (new RequirementsHandler)->Register();
(new SandboxedPageHandler)->Register(); (new SandboxedPageHandler)->Register();
(new SharedModuleHandler)->Register(); (new SharedModuleHandler)->Register();
(new SocketsManifestHandler)->Register(); (new SocketsManifestHandler)->Register();
......
...@@ -739,6 +739,7 @@ const char kMultipleOverrides[] = ...@@ -739,6 +739,7 @@ const char kMultipleOverrides[] =
"An extension cannot override more than one page."; "An extension cannot override more than one page.";
const char kNoWildCardsInPaths[] = const char kNoWildCardsInPaths[] =
"Wildcards are not allowed in extent URL pattern paths."; "Wildcards are not allowed in extent URL pattern paths.";
const char kNPAPIPluginsNotSupported[] = "NPAPI plugins are not supported.";
const char kOneUISurfaceOnly[] = const char kOneUISurfaceOnly[] =
"Only one of 'browser_action', 'page_action', and 'app' can be specified."; "Only one of 'browser_action', 'page_action', and 'app' can be specified.";
const char kPermissionMustBeOptional[] = const char kPermissionMustBeOptional[] =
...@@ -749,6 +750,8 @@ const char kPermissionNotAllowedInManifest[] = ...@@ -749,6 +750,8 @@ const char kPermissionNotAllowedInManifest[] =
"Permission '*' cannot be specified in the manifest."; "Permission '*' cannot be specified in the manifest.";
const char kPermissionUnknownOrMalformed[] = const char kPermissionUnknownOrMalformed[] =
"Permission '*' is unknown or URL pattern is malformed."; "Permission '*' is unknown or URL pattern is malformed.";
const char kPluginsRequirementDeprecated[] =
"The \"plugins\" requirement is deprecated.";
const char kReservedMessageFound[] = const char kReservedMessageFound[] =
"Reserved key * found in message catalog."; "Reserved key * found in message catalog.";
const char kRulesFileIsInvalid[] = const char kRulesFileIsInvalid[] =
......
...@@ -495,11 +495,13 @@ extern const char kManifestUnreadable[]; ...@@ -495,11 +495,13 @@ extern const char kManifestUnreadable[];
extern const char kMissingFile[]; extern const char kMissingFile[];
extern const char kMultipleOverrides[]; extern const char kMultipleOverrides[];
extern const char kNoWildCardsInPaths[]; extern const char kNoWildCardsInPaths[];
extern const char kNPAPIPluginsNotSupported[];
extern const char kOneUISurfaceOnly[]; extern const char kOneUISurfaceOnly[];
extern const char kPermissionMustBeOptional[]; extern const char kPermissionMustBeOptional[];
extern const char kPermissionNotAllowed[]; extern const char kPermissionNotAllowed[];
extern const char kPermissionNotAllowedInManifest[]; extern const char kPermissionNotAllowedInManifest[];
extern const char kPermissionUnknownOrMalformed[]; extern const char kPermissionUnknownOrMalformed[];
extern const char kPluginsRequirementDeprecated[];
extern const char kReservedMessageFound[]; extern const char kReservedMessageFound[];
extern const char kRulesFileIsInvalid[]; extern const char kRulesFileIsInvalid[];
extern const char kUnrecognizedManifestKey[]; extern const char kUnrecognizedManifestKey[];
......
...@@ -18,15 +18,7 @@ namespace keys = manifest_keys; ...@@ -18,15 +18,7 @@ namespace keys = manifest_keys;
namespace errors = manifest_errors; namespace errors = manifest_errors;
RequirementsInfo::RequirementsInfo(const Manifest* manifest) RequirementsInfo::RequirementsInfo(const Manifest* manifest)
: webgl(false), : webgl(false), window_shape(false) {}
npapi(false),
window_shape(false) {
// Before parsing requirements from the manifest, automatically default the
// NPAPI plugin requirement based on whether it includes NPAPI plugins.
const base::ListValue* list_value = NULL;
npapi = manifest->GetList(keys::kPlugins, &list_value) &&
!list_value->empty();
}
RequirementsInfo::~RequirementsInfo() { RequirementsInfo::~RequirementsInfo() {
} }
...@@ -49,10 +41,6 @@ RequirementsHandler::RequirementsHandler() { ...@@ -49,10 +41,6 @@ RequirementsHandler::RequirementsHandler() {
RequirementsHandler::~RequirementsHandler() { RequirementsHandler::~RequirementsHandler() {
} }
const std::vector<std::string> RequirementsHandler::PrerequisiteKeys() const {
return SingleKey(keys::kPlugins);
}
const std::vector<std::string> RequirementsHandler::Keys() const { const std::vector<std::string> RequirementsHandler::Keys() const {
return SingleKey(keys::kRequirements); return SingleKey(keys::kRequirements);
} }
...@@ -87,23 +75,18 @@ bool RequirementsHandler::Parse(Extension* extension, base::string16* error) { ...@@ -87,23 +75,18 @@ bool RequirementsHandler::Parse(Extension* extension, base::string16* error) {
return false; return false;
} }
// The plugins requirement is deprecated. Raise an install warning. If the
// extension explicitly requires npapi plugins, raise an error.
if (iter.key() == "plugins") { if (iter.key() == "plugins") {
for (base::DictionaryValue::Iterator plugin_iter(*requirement_value); extension->AddInstallWarning(
!plugin_iter.IsAtEnd(); plugin_iter.Advance()) { InstallWarning(errors::kPluginsRequirementDeprecated));
bool plugin_required = false; bool requires_npapi = false;
if (!plugin_iter.value().GetAsBoolean(&plugin_required)) { if (requirement_value->GetBooleanWithoutPathExpansion("npapi",
*error = ErrorUtils::FormatErrorMessageUTF16( &requires_npapi) &&
errors::kInvalidRequirement, iter.key()); requires_npapi) {
*error = base::ASCIIToUTF16(errors::kNPAPIPluginsNotSupported);
return false; return false;
} }
if (plugin_iter.key() == "npapi") {
requirements->npapi = plugin_required;
} else {
*error = ErrorUtils::FormatErrorMessageUTF16(
errors::kInvalidRequirement, iter.key());
return false;
}
}
} else if (iter.key() == "3D") { } else if (iter.key() == "3D") {
const base::ListValue* features = NULL; const base::ListValue* features = NULL;
if (!requirement_value->GetListWithoutPathExpansion("features", if (!requirement_value->GetListWithoutPathExpansion("features",
......
...@@ -21,7 +21,6 @@ struct RequirementsInfo : public Extension::ManifestData { ...@@ -21,7 +21,6 @@ struct RequirementsInfo : public Extension::ManifestData {
~RequirementsInfo() override; ~RequirementsInfo() override;
bool webgl; bool webgl;
bool npapi;
bool window_shape; bool window_shape;
static const RequirementsInfo& GetRequirements(const Extension* extension); static const RequirementsInfo& GetRequirements(const Extension* extension);
...@@ -37,8 +36,6 @@ class RequirementsHandler : public ManifestHandler { ...@@ -37,8 +36,6 @@ class RequirementsHandler : public ManifestHandler {
bool AlwaysParseForType(Manifest::Type type) const override; bool AlwaysParseForType(Manifest::Type type) const override;
const std::vector<std::string> PrerequisiteKeys() const override;
private: private:
const std::vector<std::string> Keys() const override; const std::vector<std::string> Keys() const override;
......
...@@ -311,11 +311,6 @@ ...@@ -311,11 +311,6 @@
<message name="IDS_EXTENSION_INSTALL_PROCESS_CRASHED" desc="Error message in case package fails to install because a utility process crashed."> <message name="IDS_EXTENSION_INSTALL_PROCESS_CRASHED" desc="Error message in case package fails to install because a utility process crashed.">
Could not install package because a utility process crashed. Try restarting Chrome and trying again. Could not install package because a utility process crashed. Try restarting Chrome and trying again.
</message> </message>
<if expr="is_posix and not is_macosx">
<message name="IDS_EXTENSION_NPAPI_NOT_SUPPORTED" desc="Error message when an extension has a requirement for plugins that the system does not support.">
NPAPI plugins are not supported.
</message>
</if>
<message name="IDS_EXTENSION_PACKAGE_ERROR_CODE" desc="Error message in cases where we fail to install the extension because the crx file is invalid. For example, because the crx header or signature is invalid."> <message name="IDS_EXTENSION_PACKAGE_ERROR_CODE" desc="Error message in cases where we fail to install the extension because the crx file is invalid. For example, because the crx header or signature is invalid.">
Package is invalid: '<ph name="ERROR_CODE">$1<ex>error</ex></ph>'. Package is invalid: '<ph name="ERROR_CODE">$1<ex>error</ex></ph>'.
</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