blob: 5abd7654871c223aabd0ea92a6e2848b71da2c09 [file] [log] [blame]
// Copyright (c) 2012 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 "content/shell/renderer/shell_content_renderer_client.h"
#include <string>
#include "base/bind.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "components/cdm/renderer/external_clear_key_key_system_properties.h"
#include "components/web_cache/renderer/web_cache_impl.h"
#include "content/public/test/test_service.mojom.h"
#include "content/shell/common/power_monitor_test_impl.h"
#include "content/shell/common/shell_switches.h"
#include "content/shell/renderer/shell_render_frame_observer.h"
#include "mojo/public/cpp/bindings/binder_map.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "net/base/net_errors.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/service_manager/sandbox/sandbox.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/web/web_testing_support.h"
#include "third_party/blink/public/web/web_view.h"
#include "v8/include/v8.h"
#if BUILDFLAG(ENABLE_PLUGINS)
#include "ppapi/shared_impl/ppapi_switches.h" // nogncheck
#endif
#if BUILDFLAG(ENABLE_MOJO_CDM)
#include "base/feature_list.h"
#include "media/base/media_switches.h"
#endif
namespace content {
namespace {
// A test service which can be driven by browser tests for various reasons.
class TestRendererServiceImpl : public mojom::TestService {
public:
explicit TestRendererServiceImpl(
mojo::PendingReceiver<mojom::TestService> receiver)
: receiver_(this, std::move(receiver)) {
receiver_.set_disconnect_handler(base::BindOnce(
&TestRendererServiceImpl::OnConnectionError, base::Unretained(this)));
}
~TestRendererServiceImpl() override {}
private:
void OnConnectionError() { delete this; }
// mojom::TestService:
void DoSomething(DoSomethingCallback callback) override {
// Instead of responding normally, unbind the pipe, write some garbage,
// and go away.
const std::string kBadMessage = "This is definitely not a valid response!";
mojo::ScopedMessagePipeHandle pipe = receiver_.Unbind().PassPipe();
MojoResult rv = mojo::WriteMessageRaw(
pipe.get(), kBadMessage.data(), kBadMessage.size(), nullptr, 0,
MOJO_WRITE_MESSAGE_FLAG_NONE);
DCHECK_EQ(rv, MOJO_RESULT_OK);
// Deletes this.
OnConnectionError();
}
void DoTerminateProcess(DoTerminateProcessCallback callback) override {
NOTREACHED();
}
void DoCrashImmediately(DoCrashImmediatelyCallback callback) override {
NOTREACHED();
}
void CreateFolder(CreateFolderCallback callback) override { NOTREACHED(); }
void GetRequestorName(GetRequestorNameCallback callback) override {
std::move(callback).Run("Not implemented.");
}
void CreateReadOnlySharedMemoryRegion(
const std::string& message,
CreateReadOnlySharedMemoryRegionCallback callback) override {
NOTREACHED();
}
void CreateWritableSharedMemoryRegion(
const std::string& message,
CreateWritableSharedMemoryRegionCallback callback) override {
NOTREACHED();
}
void CreateUnsafeSharedMemoryRegion(
const std::string& message,
CreateUnsafeSharedMemoryRegionCallback callback) override {
NOTREACHED();
}
void IsProcessSandboxed(IsProcessSandboxedCallback callback) override {
std::move(callback).Run(service_manager::Sandbox::IsProcessSandboxed());
}
mojo::Receiver<mojom::TestService> receiver_;
DISALLOW_COPY_AND_ASSIGN(TestRendererServiceImpl);
};
void CreateRendererTestService(
mojo::PendingReceiver<mojom::TestService> receiver) {
// Owns itself.
new TestRendererServiceImpl(std::move(receiver));
}
} // namespace
ShellContentRendererClient::ShellContentRendererClient() {}
ShellContentRendererClient::~ShellContentRendererClient() {
}
void ShellContentRendererClient::RenderThreadStarted() {
web_cache_impl_ = std::make_unique<web_cache::WebCacheImpl>();
}
void ShellContentRendererClient::ExposeInterfacesToBrowser(
mojo::BinderMap* binders) {
binders->Add(base::BindRepeating(&CreateRendererTestService),
base::ThreadTaskRunnerHandle::Get());
binders->Add(
base::BindRepeating(&PowerMonitorTestImpl::MakeSelfOwnedReceiver),
base::ThreadTaskRunnerHandle::Get());
binders->Add(base::BindRepeating(&web_cache::WebCacheImpl::BindReceiver,
base::Unretained(web_cache_impl_.get())),
base::ThreadTaskRunnerHandle::Get());
}
void ShellContentRendererClient::RenderFrameCreated(RenderFrame* render_frame) {
// TODO(danakj): The ShellRenderFrameObserver is doing stuff only for
// browser tests. If we only create that for browser tests then the override
// of this method in WebTestContentRendererClient would not be needed.
new ShellRenderFrameObserver(render_frame);
}
bool ShellContentRendererClient::HasErrorPage(int http_status_code) {
return http_status_code >= 400 && http_status_code < 600;
}
void ShellContentRendererClient::PrepareErrorPage(
RenderFrame* render_frame,
const blink::WebURLError& error,
const std::string& http_method,
std::string* error_html) {
if (error_html && error_html->empty()) {
*error_html =
"<head><title>Error</title></head><body>Could not load the requested "
"resource.<br/>Error code: " +
base::NumberToString(error.reason()) +
(error.reason() < 0 ? " (" + net::ErrorToString(error.reason()) + ")"
: "") +
"</body>";
}
}
void ShellContentRendererClient::PrepareErrorPageForHttpStatusError(
content::RenderFrame* render_frame,
const GURL& unreachable_url,
const std::string& http_method,
int http_status,
std::string* error_html) {
if (error_html) {
*error_html =
"<head><title>Error</title></head><body>Server returned HTTP status " +
base::NumberToString(http_status) + "</body>";
}
}
bool ShellContentRendererClient::IsPluginAllowedToUseDevChannelAPIs() {
#if BUILDFLAG(ENABLE_PLUGINS)
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnablePepperTesting);
#else
return false;
#endif
}
void ShellContentRendererClient::DidInitializeWorkerContextOnWorkerThread(
v8::Local<v8::Context> context) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kExposeInternalsForTesting)) {
blink::WebTestingSupport::InjectInternalsObject(context);
}
}
#if BUILDFLAG(ENABLE_MOJO_CDM)
void ShellContentRendererClient::AddSupportedKeySystems(
std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) {
if (!base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting))
return;
static const char kExternalClearKeyKeySystem[] =
"org.chromium.externalclearkey";
key_systems->emplace_back(
new cdm::ExternalClearKeyProperties(kExternalClearKeyKeySystem));
}
#endif
} // namespace content