blob: 3cad85d289db726e31828b89f656358bf0e069b8 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/renderer/chrome_content_renderer_client.h"
#include <stddef.h>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/common/privacy_budget/scoped_privacy_budget_config.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/webplugininfo.h"
#include "extensions/buildflags/buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "url/gurl.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/common/extensions/extension_test_util.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/extensions_client.h"
#include "extensions/common/manifest_constants.h"
#endif
#if BUILDFLAG(ENABLE_NACL)
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_plugin_params.h"
#endif
#if BUILDFLAG(ENABLE_NACL)
using blink::WebPluginParams;
using blink::WebString;
using blink::WebVector;
#endif
using content::WebPluginInfo;
using content::WebPluginMimeType;
#if BUILDFLAG(ENABLE_EXTENSIONS)
using extensions::mojom::ManifestLocation;
#endif
namespace {
#if BUILDFLAG(ENABLE_NACL)
const bool kNaClRestricted = false;
const bool kNaClUnrestricted = true;
const bool kExtensionNotFromWebStore = false;
const bool kExtensionFromWebStore = true;
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
const bool kNotHostedApp = false;
const bool kHostedApp = true;
#endif
#if BUILDFLAG(ENABLE_NACL)
const char kExtensionUrl[] = "chrome-extension://extension_id/background.html";
#endif
void AddContentTypeHandler(content::WebPluginInfo* info,
const char* mime_type,
const char* manifest_url) {
content::WebPluginMimeType mime_type_info;
mime_type_info.mime_type = mime_type;
mime_type_info.additional_params.emplace_back(
u"nacl", base::UTF8ToUTF16(manifest_url));
info->mime_types.push_back(mime_type_info);
}
} // namespace
class ChromeContentRendererClientTest : public testing::Test {
public:
void SetUp() override {
// Ensure that this looks like the renderer process based on the command
// line.
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kProcessType, switches::kRendererProcess);
}
};
#if BUILDFLAG(ENABLE_EXTENSIONS)
scoped_refptr<const extensions::Extension> CreateTestExtension(
ManifestLocation location,
bool is_from_webstore,
bool is_hosted_app,
const std::string& app_url) {
int flags = is_from_webstore ?
extensions::Extension::FROM_WEBSTORE:
extensions::Extension::NO_FLAGS;
base::Value::Dict manifest;
manifest.Set("name", "NaCl Extension");
manifest.Set("version", "1");
manifest.Set("manifest_version", 2);
if (is_hosted_app) {
base::Value::List url_list;
url_list.Append(app_url);
manifest.SetByDottedPath(extensions::manifest_keys::kWebURLs,
std::move(url_list));
manifest.SetByDottedPath(extensions::manifest_keys::kLaunchWebURL, app_url);
}
std::string error;
return extensions::Extension::Create(base::FilePath(), location, manifest,
flags, &error);
}
scoped_refptr<const extensions::Extension> CreateExtension(
bool is_from_webstore) {
return CreateTestExtension(ManifestLocation::kInternal, is_from_webstore,
kNotHostedApp, std::string());
}
scoped_refptr<const extensions::Extension> CreateExtensionWithLocation(
ManifestLocation location,
bool is_from_webstore) {
return CreateTestExtension(
location, is_from_webstore, kNotHostedApp, std::string());
}
scoped_refptr<const extensions::Extension> CreateHostedApp(
bool is_from_webstore, const std::string& app_url) {
return CreateTestExtension(ManifestLocation::kInternal, is_from_webstore,
kHostedApp, app_url);
}
TEST_F(ChromeContentRendererClientTest, ExtensionsClientInitialized) {
auto* extensions_client = extensions::ExtensionsClient::Get();
ASSERT_TRUE(extensions_client);
// Ensure that the availability map is initialized correctly.
const auto& map =
extensions_client->GetFeatureDelegatedAvailabilityCheckMap();
EXPECT_EQ(7u, map.size());
for (const auto* feature :
extension_test_util::GetExpectedDelegatedFeaturesForTest()) {
EXPECT_EQ(1u, map.count(feature));
}
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
TEST_F(ChromeContentRendererClientTest, NaClRestriction) {
// Unknown content types have no NaCl module.
{
WebPluginInfo info;
EXPECT_EQ(GURL(),
ChromeContentRendererClient::GetNaClContentHandlerURL(
"application/x-foo", info));
}
// Known content types have a NaCl module.
{
WebPluginInfo info;
AddContentTypeHandler(&info, "application/x-foo", "www.foo.com");
EXPECT_EQ(GURL("www.foo.com"),
ChromeContentRendererClient::GetNaClContentHandlerURL(
"application/x-foo", info));
}
#if BUILDFLAG(ENABLE_NACL)
// --enable-nacl allows all NaCl apps.
{
EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL(), kNaClUnrestricted,
CreateExtension(kExtensionNotFromWebStore).get()));
}
// Unpacked extensions are allowed without --enable-nacl.
{
EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL(kExtensionUrl), kNaClRestricted,
CreateExtensionWithLocation(ManifestLocation::kUnpacked,
kExtensionNotFromWebStore)
.get()));
}
// Component extensions are allowed without --enable-nacl.
{
EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL(kExtensionUrl), kNaClRestricted,
CreateExtensionWithLocation(ManifestLocation::kComponent,
kExtensionNotFromWebStore)
.get()));
}
{
EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL(kExtensionUrl), kNaClRestricted,
CreateExtensionWithLocation(ManifestLocation::kExternalComponent,
kExtensionNotFromWebStore)
.get()));
}
// Extensions that are force installed by policy are allowed without
// --enable-nacl.
{
EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL(kExtensionUrl), kNaClRestricted,
CreateExtensionWithLocation(ManifestLocation::kExternalPolicy,
kExtensionNotFromWebStore)
.get()));
EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL(kExtensionUrl), kNaClRestricted,
CreateExtensionWithLocation(ManifestLocation::kExternalPolicyDownload,
kExtensionNotFromWebStore)
.get()));
}
// CWS extensions are allowed without --enable-nacl if called from an
// extension url.
{
EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL(kExtensionUrl), kNaClRestricted,
CreateExtension(kExtensionFromWebStore).get()));
}
// Other URLs (including previously-whitelisted URLs) are blocked
// without --enable-nacl.
{
EXPECT_FALSE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL("https://plus.google.com.evil.com/foo1"), kNaClRestricted,
nullptr));
EXPECT_FALSE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL("https://talkgadget.google.com/hangouts/foo1"), kNaClRestricted,
nullptr));
}
// Non chrome-extension:// URLs belonging to hosted apps are allowed for
// webstore installed hosted apps.
{
EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL("http://example.com/test.html"), kNaClRestricted,
CreateHostedApp(kExtensionFromWebStore, "http://example.com/").get()));
EXPECT_FALSE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL("http://example.com/test.html"), kNaClRestricted,
CreateHostedApp(kExtensionNotFromWebStore, "http://example.com/")
.get()));
EXPECT_FALSE(ChromeContentRendererClient::IsNativeNaClAllowed(
GURL("http://example.evil.com/test.html"), kNaClRestricted,
CreateHostedApp(kExtensionNotFromWebStore, "http://example.com/")
.get()));
}
#endif // BUILDFLAG(ENABLE_NACL)
}