blob: b68cfd54353014ae6079223144d7775308f4781c [file] [log] [blame]
// Copyright 2017 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 "base/test/scoped_feature_list.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/features/feature_developer_mode_only.h"
#include "extensions/renderer/bindings/api_binding_test_util.h"
#include "extensions/renderer/dispatcher.h"
#include "extensions/renderer/native_extension_bindings_system.h"
#include "extensions/renderer/native_extension_bindings_system_test_base.h"
#include "extensions/renderer/script_context.h"
namespace extensions {
TEST_F(NativeExtensionBindingsSystemUnittest, InitializeContext) {
scoped_refptr<const Extension> extension =
ExtensionBuilder("foo")
.AddPermissions({"idle", "power", "webRequest", "tabs"})
.Build();
RegisterExtension(extension);
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = MainContext();
ScriptContext* script_context = CreateScriptContext(
context, extension.get(), Feature::BLESSED_EXTENSION_CONTEXT);
script_context->set_url(extension->url());
bindings_system()->UpdateBindingsForContext(script_context);
// Test that chrome-specified APIs (like tabs) are present.
v8::Local<v8::Value> chrome =
GetPropertyFromObject(context->Global(), context, "chrome");
ASSERT_FALSE(chrome.IsEmpty());
ASSERT_TRUE(chrome->IsObject());
v8::Local<v8::Value> tabs =
GetPropertyFromObject(chrome.As<v8::Object>(), context, "tabs");
ASSERT_FALSE(tabs.IsEmpty());
ASSERT_TRUE(tabs->IsObject());
v8::Local<v8::Value> query =
GetPropertyFromObject(tabs.As<v8::Object>(), context, "query");
ASSERT_FALSE(query.IsEmpty());
ASSERT_TRUE(query->IsFunction());
}
TEST_F(NativeExtensionBindingsSystemUnittest,
RestrictDeveloperModeAPIsUserIsInDeveloperMode) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
extensions_features::kRestrictDeveloperModeAPIs);
// With kDeveloperModeRestriction enabled, developer mode-only APIs
// should be available if and only if the user is in dev mode.
SetCurrentDeveloperMode(kRendererProfileId, true);
scoped_refptr<const Extension> extension =
ExtensionBuilder("foo").AddPermissions({"debugger"}).Build();
RegisterExtension(extension);
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = MainContext();
ScriptContext* script_context = CreateScriptContext(
context, extension.get(), Feature::BLESSED_EXTENSION_CONTEXT);
script_context->set_url(extension->url());
bindings_system()->UpdateBindingsForContext(script_context);
// chrome.debugger.getTargets should exist.
v8::Local<v8::Value> chrome =
GetPropertyFromObject(context->Global(), context, "chrome");
ASSERT_FALSE(chrome.IsEmpty());
ASSERT_TRUE(chrome->IsObject());
v8::Local<v8::Value> debugger = GetPropertyFromObject(
v8::Local<v8::Object>::Cast(chrome), context, "debugger");
ASSERT_FALSE(debugger.IsEmpty());
ASSERT_TRUE(debugger->IsObject());
v8::Local<v8::Object> debugger_object = v8::Local<v8::Object>::Cast(debugger);
v8::Local<v8::Value> debugger_getTargets =
GetPropertyFromObject(debugger_object, context, "getTargets");
ASSERT_FALSE(debugger_getTargets.IsEmpty());
{
// Call the function correctly.
const char kCallDebuggerGetTargets[] =
R"((function() {
chrome.debugger.getTargets(function() {});
});)";
v8::Local<v8::Function> call_debugger_getTargets =
FunctionFromString(context, kCallDebuggerGetTargets);
RunFunctionOnGlobal(call_debugger_getTargets, context, 0, nullptr);
}
// Validate the params that would be sent to the browser.
EXPECT_EQ(extension->id(), last_params().extension_id);
EXPECT_EQ("debugger.getTargets", last_params().name);
EXPECT_EQ(extension->url(), last_params().source_url);
EXPECT_TRUE(last_params().has_callback);
EXPECT_EQ(last_params().arguments, *DeprecatedListValueFromString("[ ]"));
}
TEST_F(NativeExtensionBindingsSystemUnittest,
RestrictDeveloperModeAPIsUserIsNotInDeveloperModeAndHasPermission) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
extensions_features::kRestrictDeveloperModeAPIs);
// With kDeveloperModeRestriction enabled, developer mode-only APIs
// should not be available if the user is not in dev mode.
SetCurrentDeveloperMode(kRendererProfileId, false);
scoped_refptr<const Extension> extension =
ExtensionBuilder("foo").AddPermissions({"debugger"}).Build();
RegisterExtension(extension);
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = MainContext();
ScriptContext* script_context = CreateScriptContext(
context, extension.get(), Feature::BLESSED_EXTENSION_CONTEXT);
script_context->set_url(extension->url());
bindings_system()->UpdateBindingsForContext(script_context);
v8::Local<v8::Value> chrome =
GetPropertyFromObject(context->Global(), context, "chrome");
ASSERT_FALSE(chrome.IsEmpty());
ASSERT_TRUE(chrome->IsObject());
{
const char kCallDebuggerGetTargets[] =
R"((function() {
chrome.debugger(function() {});
});)";
v8::Local<v8::Function> call_debugger_getTargets =
FunctionFromString(context, kCallDebuggerGetTargets);
RunFunctionAndExpectError(call_debugger_getTargets, context, 0, nullptr,
"Uncaught Error: The 'debugger' API is only "
"available for users in developer mode.");
}
}
TEST_F(
NativeExtensionBindingsSystemUnittest,
RestrictDeveloperModeAPIsUserIsNotInDeveloperModeAndDoesNotHavePermission) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
extensions_features::kRestrictDeveloperModeAPIs);
SetCurrentDeveloperMode(kRendererProfileId, false);
scoped_refptr<const Extension> extension = ExtensionBuilder("foo").Build();
RegisterExtension(extension);
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = MainContext();
ScriptContext* script_context = CreateScriptContext(
context, extension.get(), Feature::BLESSED_EXTENSION_CONTEXT);
script_context->set_url(extension->url());
bindings_system()->UpdateBindingsForContext(script_context);
v8::Local<v8::Value> chrome =
GetPropertyFromObject(context->Global(), context, "chrome");
ASSERT_FALSE(chrome.IsEmpty());
ASSERT_TRUE(chrome->IsObject());
v8::Local<v8::Value> debugger = GetPropertyFromObject(
v8::Local<v8::Object>::Cast(chrome), context, "debugger");
ASSERT_FALSE(debugger.IsEmpty());
EXPECT_TRUE(debugger->IsUndefined());
}
} // namespace extensions