Remove uses of shell::Loader from content
Replaces existing uses with the same SCF-based interface used for other shell connections. Adds a manifest for mojo:media (packaged in exe:content_browser) so the shell knows where to route its connections. BUG=601884 CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_site_isolation TBR=xhwang@chromium.org for addition of the app manifest Review URL: https://codereview.chromium.org/1889253002 Cr-Commit-Position: refs/heads/master@{#387708}
This commit is contained in:
content
browser
child
common
content_common.gypicontent_tests.gypigpu
public
app
shell
test
utility
media/mojo/services
@ -9,7 +9,6 @@
|
||||
#include "build/build_config.h"
|
||||
#include "content/browser/mojo/mojo_shell_context.h"
|
||||
#include "content/common/mojo/service_registry_impl.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/content_browser_client.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
@ -58,10 +57,8 @@ void FrameMojoShell::Connect(
|
||||
shell::mojom::InterfaceProviderPtr frame_services;
|
||||
service_provider_bindings_.AddBinding(GetServiceRegistry(),
|
||||
GetProxy(&frame_services));
|
||||
std::string mojo_user_id = BrowserContext::GetMojoUserIdFor(
|
||||
frame_host_->GetProcess()->GetBrowserContext());
|
||||
MojoShellContext::ConnectToApplication(
|
||||
mojo_user_id, target->name,
|
||||
shell::mojom::kRootUserID, target->name,
|
||||
frame_host_->GetSiteInstance()->GetSiteURL().spec(), std::move(services),
|
||||
std::move(frame_services), callback);
|
||||
}
|
||||
|
@ -4,11 +4,14 @@
|
||||
|
||||
#include "content/browser/mojo/browser_shell_connection.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "content/browser/mojo/constants.h"
|
||||
#include "services/shell/public/interfaces/connector.mojom.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
BrowserShellConnection::BrowserShellConnection() {}
|
||||
|
||||
BrowserShellConnection::BrowserShellConnection(
|
||||
shell::mojom::ShellClientRequest request)
|
||||
: shell_connection_(new shell::ShellConnection(this, std::move(request))) {}
|
||||
@ -16,6 +19,7 @@ BrowserShellConnection::BrowserShellConnection(
|
||||
BrowserShellConnection::~BrowserShellConnection() {}
|
||||
|
||||
shell::Connector* BrowserShellConnection::GetConnector() {
|
||||
DCHECK(shell_connection_);
|
||||
return shell_connection_->connector();
|
||||
}
|
||||
|
||||
@ -25,11 +29,22 @@ void BrowserShellConnection::AddEmbeddedApplication(
|
||||
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
|
||||
std::unique_ptr<EmbeddedApplicationRunner> app(
|
||||
new EmbeddedApplicationRunner(callback, task_runner));
|
||||
AddShellClientRequestHandler(
|
||||
name, base::Bind(&EmbeddedApplicationRunner::BindShellClientRequest,
|
||||
base::Unretained(app.get())));
|
||||
auto result = embedded_apps_.insert(
|
||||
std::make_pair(name.as_string(), std::move(app)));
|
||||
DCHECK(result.second);
|
||||
}
|
||||
|
||||
void BrowserShellConnection::AddShellClientRequestHandler(
|
||||
const base::StringPiece& name,
|
||||
const ShellClientRequestHandler& handler) {
|
||||
auto result = request_handlers_.insert(
|
||||
std::make_pair(name.as_string(), handler));
|
||||
DCHECK(result.second);
|
||||
}
|
||||
|
||||
bool BrowserShellConnection::AcceptConnection(shell::Connection* connection) {
|
||||
std::string remote_app = connection->GetRemoteIdentity().name();
|
||||
if (remote_app == "mojo:shell") {
|
||||
@ -56,9 +71,9 @@ void BrowserShellConnection::Create(
|
||||
void BrowserShellConnection::CreateShellClient(
|
||||
shell::mojom::ShellClientRequest request,
|
||||
const mojo::String& name) {
|
||||
auto it = embedded_apps_.find(name);
|
||||
if (it != embedded_apps_.end())
|
||||
it->second->BindShellClientRequest(std::move(request));
|
||||
auto it = request_handlers_.find(name);
|
||||
if (it != request_handlers_.end())
|
||||
it->second.Run(std::move(request));
|
||||
}
|
||||
|
||||
} // namespace content
|
||||
|
@ -33,7 +33,17 @@ class BrowserShellConnection
|
||||
public shell::InterfaceFactory<shell::mojom::ShellClientFactory>,
|
||||
public shell::mojom::ShellClientFactory {
|
||||
public:
|
||||
using ShellClientRequestHandler =
|
||||
base::Callback<void(shell::mojom::ShellClientRequest)>;
|
||||
|
||||
// Constructs a connection which does not own a ShellClient pipe. This
|
||||
// connection must be manually fed new incoming connections via its
|
||||
// shell::ShellClient interface.
|
||||
BrowserShellConnection();
|
||||
|
||||
// Constructs a connection associated with its own ShellClient pipe.
|
||||
explicit BrowserShellConnection(shell::mojom::ShellClientRequest request);
|
||||
|
||||
~BrowserShellConnection() override;
|
||||
|
||||
shell::Connector* GetConnector();
|
||||
@ -48,6 +58,15 @@ class BrowserShellConnection
|
||||
const EmbeddedApplicationRunner::FactoryCallback& callback,
|
||||
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
|
||||
|
||||
// Adds a generic ShellClientRequestHandler for a given application name. This
|
||||
// will be used to satisfy any incoming calls to CreateShellClient() which
|
||||
// reference the given name.
|
||||
//
|
||||
// For in-process applications, it is preferrable to use
|
||||
// |AddEmbeddedApplication()| as defined above.
|
||||
void AddShellClientRequestHandler(const base::StringPiece& name,
|
||||
const ShellClientRequestHandler& handler);
|
||||
|
||||
private:
|
||||
// shell::ShellClient:
|
||||
bool AcceptConnection(shell::Connection* connection) override;
|
||||
@ -64,6 +83,7 @@ class BrowserShellConnection
|
||||
mojo::BindingSet<shell::mojom::ShellClientFactory> factory_bindings_;
|
||||
std::unordered_map<std::string, std::unique_ptr<EmbeddedApplicationRunner>>
|
||||
embedded_apps_;
|
||||
std::unordered_map<std::string, ShellClientRequestHandler> request_handlers_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserShellConnection);
|
||||
};
|
||||
|
@ -16,10 +16,10 @@
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "content/browser/gpu/gpu_process_host.h"
|
||||
#include "content/browser/mojo/browser_shell_connection.h"
|
||||
#include "content/browser/mojo/constants.h"
|
||||
#include "content/common/gpu_process_launch_causes.h"
|
||||
#include "content/common/mojo/mojo_shell_connection_impl.h"
|
||||
#include "content/common/mojo/static_loader.h"
|
||||
#include "content/common/process_control.mojom.h"
|
||||
#include "content/grit/content_resources.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
@ -35,11 +35,12 @@
|
||||
#include "services/catalog/manifest_provider.h"
|
||||
#include "services/catalog/store.h"
|
||||
#include "services/shell/connect_params.h"
|
||||
#include "services/shell/loader.h"
|
||||
#include "services/shell/native_runner.h"
|
||||
#include "services/shell/public/cpp/identity.h"
|
||||
#include "services/shell/public/cpp/shell_client.h"
|
||||
#include "services/shell/public/interfaces/connector.mojom.h"
|
||||
#include "services/shell/public/interfaces/shell_client.mojom.h"
|
||||
#include "services/shell/public/interfaces/shell_client_factory.mojom.h"
|
||||
#include "services/shell/runner/host/in_process_native_runner.h"
|
||||
#include "services/user/public/cpp/constants.h"
|
||||
|
||||
@ -70,34 +71,22 @@ void OnApplicationLoaded(const std::string& name, bool success) {
|
||||
LOG(ERROR) << "Failed to launch Mojo application for " << name;
|
||||
}
|
||||
|
||||
// This launches a utility process and forwards the Load request the
|
||||
// mojom::ProcessControl service there. The utility process is sandboxed iff
|
||||
// |use_sandbox| is true.
|
||||
class UtilityProcessLoader : public shell::Loader {
|
||||
public:
|
||||
UtilityProcessLoader(const base::string16& process_name, bool use_sandbox)
|
||||
: process_name_(process_name), use_sandbox_(use_sandbox) {}
|
||||
~UtilityProcessLoader() override {}
|
||||
void LaunchAppInUtilityProcess(const std::string& app_name,
|
||||
const base::string16& process_name,
|
||||
bool use_sandbox,
|
||||
shell::mojom::ShellClientRequest request) {
|
||||
mojom::ProcessControlPtr process_control;
|
||||
mojom::ProcessControlRequest process_request =
|
||||
mojo::GetProxy(&process_control);
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&StartUtilityProcessOnIOThread,
|
||||
base::Passed(&process_request),
|
||||
process_name, use_sandbox));
|
||||
process_control->LoadApplication(app_name, std::move(request),
|
||||
base::Bind(&OnApplicationLoaded, app_name));
|
||||
}
|
||||
|
||||
private:
|
||||
// shell::Loader:
|
||||
void Load(const std::string& name,
|
||||
shell::mojom::ShellClientRequest request) override {
|
||||
mojom::ProcessControlPtr process_control;
|
||||
auto process_request = mojo::GetProxy(&process_control);
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&StartUtilityProcessOnIOThread,
|
||||
base::Passed(&process_request),
|
||||
process_name_, use_sandbox_));
|
||||
process_control->LoadApplication(name, std::move(request),
|
||||
base::Bind(&OnApplicationLoaded, name));
|
||||
}
|
||||
|
||||
const base::string16 process_name_;
|
||||
const bool use_sandbox_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(UtilityProcessLoader);
|
||||
};
|
||||
#if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
|
||||
|
||||
// Request mojom::ProcessControl from GPU process host. Must be called on IO
|
||||
// thread.
|
||||
@ -120,27 +109,19 @@ void RequestGpuProcessControl(
|
||||
std::move(request));
|
||||
}
|
||||
|
||||
// Forwards the load request to the GPU process.
|
||||
class GpuProcessLoader : public shell::Loader {
|
||||
public:
|
||||
GpuProcessLoader() {}
|
||||
~GpuProcessLoader() override {}
|
||||
void LaunchAppInGpuProcess(const std::string& app_name,
|
||||
shell::mojom::ShellClientRequest request) {
|
||||
mojom::ProcessControlPtr process_control;
|
||||
mojom::ProcessControlRequest process_request =
|
||||
mojo::GetProxy(&process_control);
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&RequestGpuProcessControl, base::Passed(&process_request)));
|
||||
process_control->LoadApplication(app_name, std::move(request),
|
||||
base::Bind(&OnApplicationLoaded, app_name));
|
||||
}
|
||||
|
||||
private:
|
||||
// shell::Loader:
|
||||
void Load(const std::string& name,
|
||||
shell::mojom::ShellClientRequest request) override {
|
||||
mojom::ProcessControlPtr process_control;
|
||||
auto process_request = mojo::GetProxy(&process_control);
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&RequestGpuProcessControl, base::Passed(&process_request)));
|
||||
process_control->LoadApplication(name, std::move(request),
|
||||
base::Bind(&OnApplicationLoaded, name));
|
||||
}
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GpuProcessLoader);
|
||||
};
|
||||
#endif // ENABLE_MOJO_MEDIA_IN_GPU_PROCESS
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -216,6 +197,26 @@ class MojoShellContext::Proxy {
|
||||
DISALLOW_COPY_AND_ASSIGN(Proxy);
|
||||
};
|
||||
|
||||
// Used to attach an existing ShellClient instance as a listener on the global
|
||||
// MojoShellConnection.
|
||||
// TODO(rockot): Find a way to get rid of this.
|
||||
class ShellConnectionListener : public MojoShellConnection::Listener {
|
||||
public:
|
||||
ShellConnectionListener(std::unique_ptr<shell::ShellClient> client)
|
||||
: client_(std::move(client)) {}
|
||||
~ShellConnectionListener() override {}
|
||||
|
||||
private:
|
||||
// MojoShellConnection::Listener:
|
||||
bool AcceptConnection(shell::Connection* connection) override {
|
||||
return client_->AcceptConnection(connection);
|
||||
}
|
||||
|
||||
std::unique_ptr<shell::ShellClient> client_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ShellConnectionListener);
|
||||
};
|
||||
|
||||
// static
|
||||
base::LazyInstance<std::unique_ptr<MojoShellContext::Proxy>>
|
||||
MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER;
|
||||
@ -249,6 +250,15 @@ MojoShellContext::MojoShellContext() {
|
||||
shell_.reset(new shell::Shell(std::move(native_runner_factory),
|
||||
catalog_->TakeShellClient()));
|
||||
|
||||
if (!IsRunningInMojoShell()) {
|
||||
MojoShellConnection::Create(
|
||||
shell_->InitInstanceForEmbedder(kBrowserMojoApplicationName),
|
||||
false /* is_external */);
|
||||
}
|
||||
|
||||
std::unique_ptr<BrowserShellConnection> browser_shell_connection(
|
||||
new BrowserShellConnection);
|
||||
|
||||
StaticApplicationMap apps;
|
||||
GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps);
|
||||
if (g_applications_for_test) {
|
||||
@ -258,8 +268,8 @@ MojoShellContext::MojoShellContext() {
|
||||
apps[entry.first] = entry.second;
|
||||
}
|
||||
for (const auto& entry : apps) {
|
||||
shell_->SetLoaderForName(base::WrapUnique(new StaticLoader(entry.second)),
|
||||
entry.first);
|
||||
browser_shell_connection->AddEmbeddedApplication(
|
||||
entry.first, entry.second, nullptr);
|
||||
}
|
||||
|
||||
ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps;
|
||||
@ -267,9 +277,10 @@ MojoShellContext::MojoShellContext() {
|
||||
->browser()
|
||||
->RegisterOutOfProcessMojoApplications(&sandboxed_apps);
|
||||
for (const auto& app : sandboxed_apps) {
|
||||
shell_->SetLoaderForName(base::WrapUnique(new UtilityProcessLoader(
|
||||
app.second, true /* use_sandbox */)),
|
||||
app.first);
|
||||
browser_shell_connection->AddShellClientRequestHandler(
|
||||
app.first,
|
||||
base::Bind(&LaunchAppInUtilityProcess, app.first, app.second,
|
||||
true /* use_sandbox */));
|
||||
}
|
||||
|
||||
ContentBrowserClient::OutOfProcessMojoApplicationMap unsandboxed_apps;
|
||||
@ -277,21 +288,22 @@ MojoShellContext::MojoShellContext() {
|
||||
->browser()
|
||||
->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps);
|
||||
for (const auto& app : unsandboxed_apps) {
|
||||
shell_->SetLoaderForName(base::WrapUnique(new UtilityProcessLoader(
|
||||
app.second, false /* use_sandbox */)),
|
||||
app.first);
|
||||
browser_shell_connection->AddShellClientRequestHandler(
|
||||
app.first,
|
||||
base::Bind(&LaunchAppInUtilityProcess, app.first, app.second,
|
||||
false /* use_sandbox */));
|
||||
}
|
||||
|
||||
#if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
|
||||
shell_->SetLoaderForName(base::WrapUnique(new GpuProcessLoader),
|
||||
"mojo:media");
|
||||
browser_shell_connection->AddShellClientRequestHandler(
|
||||
"mojo:media", base::Bind(&LaunchAppInGpuProcess, "mojo:media"));
|
||||
#endif
|
||||
|
||||
if (!IsRunningInMojoShell()) {
|
||||
MojoShellConnection::Create(
|
||||
shell_->InitInstanceForEmbedder(kBrowserMojoApplicationName),
|
||||
false /* is_external */);
|
||||
}
|
||||
// Attach our ShellClientFactory implementation to the global connection.
|
||||
MojoShellConnection* shell_connection = MojoShellConnection::Get();
|
||||
CHECK(shell_connection);
|
||||
shell_connection->AddListener(
|
||||
new ShellConnectionListener(std::move(browser_shell_connection)));
|
||||
}
|
||||
|
||||
MojoShellContext::~MojoShellContext() {
|
||||
|
@ -1,72 +0,0 @@
|
||||
// Copyright 2015 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 <memory>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "content/browser/mojo/mojo_shell_context.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/mojo_app_connection.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/test/content_browser_test.h"
|
||||
#include "content/public/test/test_mojo_app.h"
|
||||
#include "content/public/test/test_mojo_service.mojom.h"
|
||||
#include "content/shell/browser/shell.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
const char kInProcessTestMojoAppName[] = "system:content_in_process_test_app";
|
||||
|
||||
class MojoShellTest : public ContentBrowserTest {
|
||||
public:
|
||||
MojoShellTest() {
|
||||
test_apps_[kInProcessTestMojoAppName] = base::Bind(&CreateTestApp);
|
||||
MojoShellContext::SetApplicationsForTest(&test_apps_);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string GetUserId() {
|
||||
return BrowserContext::GetMojoUserIdFor(
|
||||
shell()->web_contents()->GetBrowserContext());
|
||||
}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<shell::ShellClient> CreateTestApp() {
|
||||
return std::unique_ptr<shell::ShellClient>(new TestMojoApp);
|
||||
}
|
||||
|
||||
MojoShellContext::StaticApplicationMap test_apps_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MojoShellTest);
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(MojoShellTest, TestBrowserConnection) {
|
||||
auto test_app = MojoAppConnection::Create(
|
||||
GetUserId(), kInProcessTestMojoAppName, kBrowserMojoAppUrl);
|
||||
mojom::TestMojoServicePtr test_service;
|
||||
test_app->GetInterface(&test_service);
|
||||
|
||||
base::RunLoop run_loop;
|
||||
test_service->DoSomething(run_loop.QuitClosure());
|
||||
run_loop.Run();
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(MojoShellTest, TestUtilityConnection) {
|
||||
// With no loader registered at this URL, the shell should spawn a utility
|
||||
// process and connect us to it. content_shell's utility process always hosts
|
||||
// a TestMojoApp at |kTestMojoAppUrl|.
|
||||
auto test_app = MojoAppConnection::Create(GetUserId(), kTestMojoAppUrl,
|
||||
kBrowserMojoAppUrl);
|
||||
mojom::TestMojoServicePtr test_service;
|
||||
test_app->GetInterface(&test_service);
|
||||
|
||||
base::RunLoop run_loop;
|
||||
test_service->DoSomething(run_loop.QuitClosure());
|
||||
run_loop.Run();
|
||||
}
|
||||
|
||||
} // namespace content
|
@ -228,22 +228,5 @@ IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
|
||||
other_shell->web_contents()->GetRenderProcessHost());
|
||||
}
|
||||
|
||||
// Loads a webui page that connects to a test Mojo application via the browser's
|
||||
// Mojo shell interface.
|
||||
IN_PROC_BROWSER_TEST_F(WebUIMojoTest, ConnectToApplication) {
|
||||
if (!IsGeneratedResourceAvailable(
|
||||
"content/public/test/test_mojo_service.mojom"))
|
||||
return;
|
||||
|
||||
ASSERT_TRUE(embedded_test_server()->Start());
|
||||
NavigateToURL(shell(),
|
||||
GURL("chrome://mojo-web-ui/web_ui_mojo_shell_test.html"));
|
||||
|
||||
DOMMessageQueue message_queue;
|
||||
std::string message;
|
||||
ASSERT_TRUE(message_queue.WaitForMessage(&message));
|
||||
EXPECT_EQ("true", message);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace content
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "base/stl_util.h"
|
||||
#include "content/common/mojo/static_loader.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "content/public/common/content_client.h"
|
||||
|
||||
namespace content {
|
||||
@ -16,29 +16,36 @@ ProcessControlImpl::ProcessControlImpl() {
|
||||
}
|
||||
|
||||
ProcessControlImpl::~ProcessControlImpl() {
|
||||
STLDeleteValues(&name_to_loader_map_);
|
||||
}
|
||||
|
||||
void ProcessControlImpl::LoadApplication(
|
||||
const mojo::String& name,
|
||||
mojo::InterfaceRequest<shell::mojom::ShellClient> request,
|
||||
shell::mojom::ShellClientRequest request,
|
||||
const LoadApplicationCallback& callback) {
|
||||
// Only register loaders when we need it.
|
||||
if (!has_registered_loaders_) {
|
||||
DCHECK(name_to_loader_map_.empty());
|
||||
RegisterLoaders(&name_to_loader_map_);
|
||||
has_registered_loaders_ = true;
|
||||
// Only register apps on first run.
|
||||
if (!has_registered_apps_) {
|
||||
DCHECK(apps_.empty());
|
||||
ApplicationFactoryMap app_factories;
|
||||
RegisterApplicationFactories(&app_factories);
|
||||
for (const auto& factory : app_factories) {
|
||||
std::unique_ptr<EmbeddedApplicationRunner> runner(
|
||||
new EmbeddedApplicationRunner(factory.second, nullptr));
|
||||
runner->SetQuitClosure(base::Bind(&ProcessControlImpl::OnApplicationQuit,
|
||||
base::Unretained(this)));
|
||||
apps_.insert(std::make_pair(factory.first, std::move(runner)));
|
||||
}
|
||||
has_registered_apps_ = true;
|
||||
}
|
||||
|
||||
auto it = name_to_loader_map_.find(name);
|
||||
if (it == name_to_loader_map_.end()) {
|
||||
auto it = apps_.find(name);
|
||||
if (it == apps_.end()) {
|
||||
callback.Run(false);
|
||||
OnLoadFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
callback.Run(true);
|
||||
it->second->Load(name, std::move(request));
|
||||
it->second->BindShellClientRequest(std::move(request));
|
||||
}
|
||||
|
||||
} // namespace content
|
||||
|
@ -5,42 +5,42 @@
|
||||
#ifndef CONTENT_CHILD_PROCESS_CONTROL_IMPL_H_
|
||||
#define CONTENT_CHILD_PROCESS_CONTROL_IMPL_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "content/common/mojo/embedded_application_runner.h"
|
||||
#include "content/common/process_control.mojom.h"
|
||||
#include "mojo/public/cpp/bindings/interface_request.h"
|
||||
#include "services/shell/public/interfaces/shell_client.mojom.h"
|
||||
|
||||
namespace shell {
|
||||
class Loader;
|
||||
} // namespace shell
|
||||
|
||||
namespace content {
|
||||
|
||||
// Default implementation of the mojom::ProcessControl interface.
|
||||
class ProcessControlImpl : public mojom::ProcessControl {
|
||||
public:
|
||||
using ApplicationFactoryMap =
|
||||
std::unordered_map<std::string,
|
||||
EmbeddedApplicationRunner::FactoryCallback>;
|
||||
|
||||
ProcessControlImpl();
|
||||
~ProcessControlImpl() override;
|
||||
|
||||
using NameToLoaderMap = std::map<std::string, shell::Loader*>;
|
||||
|
||||
// Registers Mojo loaders for names.
|
||||
virtual void RegisterLoaders(NameToLoaderMap* name_to_loader_map) = 0;
|
||||
virtual void RegisterApplicationFactories(
|
||||
ApplicationFactoryMap* factories) = 0;
|
||||
virtual void OnApplicationQuit() {}
|
||||
|
||||
// ProcessControl:
|
||||
void LoadApplication(
|
||||
const mojo::String& name,
|
||||
mojo::InterfaceRequest<shell::mojom::ShellClient> request,
|
||||
const LoadApplicationCallback& callback) override;
|
||||
void LoadApplication(const mojo::String& name,
|
||||
shell::mojom::ShellClientRequest request,
|
||||
const LoadApplicationCallback& callback) override;
|
||||
|
||||
private:
|
||||
// Called if a LoadApplication request fails.
|
||||
virtual void OnLoadFailed() {}
|
||||
|
||||
bool has_registered_loaders_ = false;
|
||||
NameToLoaderMap name_to_loader_map_;
|
||||
bool has_registered_apps_ = false;
|
||||
std::unordered_map<std::string, std::unique_ptr<EmbeddedApplicationRunner>>
|
||||
apps_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ProcessControlImpl);
|
||||
};
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "base/bind.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "services/shell/public/cpp/shell_connection.h"
|
||||
@ -19,8 +20,11 @@ class EmbeddedApplicationRunner::Instance
|
||||
: public base::RefCountedThreadSafe<Instance> {
|
||||
public:
|
||||
explicit Instance(
|
||||
const EmbeddedApplicationRunner::FactoryCallback& callback)
|
||||
: factory_callback_(callback) {
|
||||
const EmbeddedApplicationRunner::FactoryCallback& callback,
|
||||
const base::Closure& quit_closure)
|
||||
: factory_callback_(callback),
|
||||
quit_closure_(quit_closure),
|
||||
quit_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
|
||||
// This object may be used exclusively from a single thread which may be
|
||||
// different from the one that created it.
|
||||
thread_checker_.DetachFromThread();
|
||||
@ -56,14 +60,18 @@ class EmbeddedApplicationRunner::Instance
|
||||
}
|
||||
}
|
||||
|
||||
if (shell_connections_.empty())
|
||||
if (shell_connections_.empty()) {
|
||||
shell_client_.reset();
|
||||
quit_task_runner_->PostTask(FROM_HERE, quit_closure_);
|
||||
}
|
||||
}
|
||||
|
||||
base::ThreadChecker thread_checker_;
|
||||
const FactoryCallback factory_callback_;
|
||||
std::unique_ptr<shell::ShellClient> shell_client_;
|
||||
std::vector<std::unique_ptr<shell::ShellConnection>> shell_connections_;
|
||||
const base::Closure quit_closure_;
|
||||
const scoped_refptr<base::SingleThreadTaskRunner> quit_task_runner_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Instance);
|
||||
};
|
||||
@ -73,7 +81,10 @@ EmbeddedApplicationRunner::EmbeddedApplicationRunner(
|
||||
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
|
||||
: application_task_runner_(
|
||||
task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get()),
|
||||
instance_(new Instance(callback)) {
|
||||
weak_factory_(this) {
|
||||
instance_ = new Instance(callback,
|
||||
base::Bind(&EmbeddedApplicationRunner::OnQuit,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
EmbeddedApplicationRunner::~EmbeddedApplicationRunner() {
|
||||
@ -87,4 +98,13 @@ void EmbeddedApplicationRunner::BindShellClientRequest(
|
||||
base::Passed(&request)));
|
||||
}
|
||||
|
||||
void EmbeddedApplicationRunner::SetQuitClosure(
|
||||
const base::Closure& quit_closure) {
|
||||
quit_closure_ = quit_closure;
|
||||
}
|
||||
|
||||
void EmbeddedApplicationRunner::OnQuit() {
|
||||
quit_closure_.Run();
|
||||
}
|
||||
|
||||
} // namespace content
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "base/callback.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "services/shell/public/cpp/shell_client.h"
|
||||
#include "services/shell/public/interfaces/shell_client.mojom.h"
|
||||
@ -41,9 +42,15 @@ class EmbeddedApplicationRunner {
|
||||
// bound to the running instance.
|
||||
void BindShellClientRequest(shell::mojom::ShellClientRequest request);
|
||||
|
||||
// Sets a callback to run after the application loses its last connection and
|
||||
// is torn down.
|
||||
void SetQuitClosure(const base::Closure& quit_closure);
|
||||
|
||||
private:
|
||||
class Instance;
|
||||
|
||||
void OnQuit();
|
||||
|
||||
// The TaskRunner on which the factory callback will be run. The
|
||||
// shell::ShellClient it returns will live and die on this TaskRunner's
|
||||
// thread.
|
||||
@ -53,6 +60,10 @@ class EmbeddedApplicationRunner {
|
||||
// |application_task_runner_|'s thread.
|
||||
scoped_refptr<Instance> instance_;
|
||||
|
||||
base::Closure quit_closure_;
|
||||
|
||||
base::WeakPtrFactory<EmbeddedApplicationRunner> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(EmbeddedApplicationRunner);
|
||||
};
|
||||
|
||||
|
@ -1,93 +0,0 @@
|
||||
// Copyright 2015 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/common/mojo/static_loader.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/task_runner.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "base/threading/simple_thread.h"
|
||||
#include "mojo/public/cpp/bindings/interface_request.h"
|
||||
#include "services/shell/public/cpp/application_runner.h"
|
||||
#include "services/shell/public/cpp/shell_client.h"
|
||||
#include "services/shell/public/interfaces/shell_client.mojom.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
namespace {
|
||||
|
||||
class RunnerThread : public base::SimpleThread {
|
||||
public:
|
||||
RunnerThread(const std::string& name,
|
||||
shell::mojom::ShellClientRequest request,
|
||||
scoped_refptr<base::TaskRunner> exit_task_runner,
|
||||
const base::Closure& exit_callback,
|
||||
const StaticLoader::ApplicationFactory& factory)
|
||||
: base::SimpleThread("Mojo Application: " + name),
|
||||
request_(std::move(request)),
|
||||
exit_task_runner_(exit_task_runner),
|
||||
exit_callback_(exit_callback),
|
||||
factory_(factory) {}
|
||||
|
||||
void Run() override {
|
||||
std::unique_ptr<shell::ApplicationRunner> runner(
|
||||
new shell::ApplicationRunner(factory_.Run().release()));
|
||||
runner->Run(request_.PassMessagePipe().release().value(),
|
||||
false /* init_base */);
|
||||
exit_task_runner_->PostTask(FROM_HERE, exit_callback_);
|
||||
}
|
||||
|
||||
private:
|
||||
shell::mojom::ShellClientRequest request_;
|
||||
scoped_refptr<base::TaskRunner> exit_task_runner_;
|
||||
base::Closure exit_callback_;
|
||||
StaticLoader::ApplicationFactory factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RunnerThread);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
StaticLoader::StaticLoader(const ApplicationFactory& factory)
|
||||
: StaticLoader(factory, base::Closure()) {
|
||||
}
|
||||
|
||||
StaticLoader::StaticLoader(const ApplicationFactory& factory,
|
||||
const base::Closure& quit_callback)
|
||||
: factory_(factory), quit_callback_(quit_callback), weak_factory_(this) {
|
||||
}
|
||||
|
||||
StaticLoader::~StaticLoader() {
|
||||
if (thread_)
|
||||
StopAppThread();
|
||||
}
|
||||
|
||||
void StaticLoader::Load(const std::string& name,
|
||||
shell::mojom::ShellClientRequest request) {
|
||||
if (thread_)
|
||||
return;
|
||||
|
||||
// If the application's thread quits on its own before this loader dies, we
|
||||
// reset the Thread object, allowing future Load requests to be fulfilled
|
||||
// with a new app instance.
|
||||
auto exit_callback = base::Bind(&StaticLoader::StopAppThread,
|
||||
weak_factory_.GetWeakPtr());
|
||||
thread_.reset(new RunnerThread(name, std::move(request),
|
||||
base::ThreadTaskRunnerHandle::Get(),
|
||||
exit_callback, factory_));
|
||||
thread_->Start();
|
||||
}
|
||||
|
||||
void StaticLoader::StopAppThread() {
|
||||
thread_->Join();
|
||||
thread_.reset();
|
||||
if (!quit_callback_.is_null())
|
||||
quit_callback_.Run();
|
||||
}
|
||||
|
||||
} // namespace content
|
@ -1,67 +0,0 @@
|
||||
// Copyright 2015 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 CONTENT_COMMON_MOJO_STATIC_APPLICATION_LOADER_H_
|
||||
#define CONTENT_COMMON_MOJO_STATIC_APPLICATION_LOADER_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "services/shell/loader.h"
|
||||
|
||||
namespace base {
|
||||
class SimpleThread;
|
||||
}
|
||||
|
||||
namespace shell {
|
||||
class ShellClient;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
|
||||
// An Loader which loads a single type of app from a given
|
||||
// shell::ShellClientFactory. A Load() request is fulfilled by creating an
|
||||
// instance of the app on a new thread. Only one instance of the app will run at
|
||||
// a time. Any Load requests received while the app is running will be dropped.
|
||||
class StaticLoader : public shell::Loader {
|
||||
public:
|
||||
using ApplicationFactory =
|
||||
base::Callback<std::unique_ptr<shell::ShellClient>()>;
|
||||
|
||||
// Constructs a static loader for |factory|.
|
||||
explicit StaticLoader(const ApplicationFactory& factory);
|
||||
|
||||
// Constructs a static loader for |factory| with a closure that will be called
|
||||
// when the loaded application quits.
|
||||
StaticLoader(const ApplicationFactory& factory,
|
||||
const base::Closure& quit_callback);
|
||||
|
||||
~StaticLoader() override;
|
||||
|
||||
// shell::Loader:
|
||||
void Load(const std::string& name,
|
||||
shell::mojom::ShellClientRequest request) override;
|
||||
|
||||
private:
|
||||
void StopAppThread();
|
||||
|
||||
// The factory used t create new instances of the application delegate.
|
||||
ApplicationFactory factory_;
|
||||
|
||||
// If not null, this is run when the loaded application quits.
|
||||
base::Closure quit_callback_;
|
||||
|
||||
// Thread for the application if currently running.
|
||||
std::unique_ptr<base::SimpleThread> thread_;
|
||||
|
||||
base::WeakPtrFactory<StaticLoader> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StaticLoader);
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
||||
#endif // CONTENT_COMMON_MOJO_STATIC_APPLICATION_LOADER_H_
|
@ -468,8 +468,6 @@
|
||||
'common/mojo/mojo_shell_connection_impl.h',
|
||||
'common/mojo/service_registry_impl.cc',
|
||||
'common/mojo/service_registry_impl.h',
|
||||
'common/mojo/static_loader.cc',
|
||||
'common/mojo/static_loader.h',
|
||||
'common/navigation_gesture.h',
|
||||
'common/navigation_params.cc',
|
||||
'common/navigation_params.h',
|
||||
|
@ -247,7 +247,6 @@
|
||||
'browser/media/session/mock_media_session_observer.h',
|
||||
'browser/memory/memory_pressure_controller_impl_browsertest.cc',
|
||||
'browser/message_port_provider_browsertest.cc',
|
||||
'browser/mojo_shell_browsertest.cc',
|
||||
'browser/net_info_browsertest.cc',
|
||||
'browser/renderer_host/input/composited_scrolling_browsertest.cc',
|
||||
'browser/renderer_host/input/non_blocking_event_browsertest.cc',
|
||||
|
@ -7,7 +7,6 @@
|
||||
#if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
|
||||
#include "base/bind.h"
|
||||
#include "base/bind_helpers.h"
|
||||
#include "content/common/mojo/static_loader.h"
|
||||
#include "media/mojo/services/mojo_media_application_factory.h"
|
||||
#endif
|
||||
|
||||
@ -17,12 +16,11 @@ GpuProcessControlImpl::GpuProcessControlImpl() {}
|
||||
|
||||
GpuProcessControlImpl::~GpuProcessControlImpl() {}
|
||||
|
||||
void GpuProcessControlImpl::RegisterLoaders(
|
||||
NameToLoaderMap* name_to_loader_map) {
|
||||
void GpuProcessControlImpl::RegisterApplicationFactories(
|
||||
ApplicationFactoryMap* factories) {
|
||||
#if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
|
||||
(*name_to_loader_map)["mojo:media"] = new StaticLoader(
|
||||
base::Bind(&media::CreateMojoMediaApplication),
|
||||
base::Bind(&base::DoNothing));
|
||||
factories->insert(std::make_pair(
|
||||
"mojo:media", base::Bind(&media::CreateMojoMediaApplication)));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class GpuProcessControlImpl : public ProcessControlImpl {
|
||||
~GpuProcessControlImpl() override;
|
||||
|
||||
// ProcessControlImpl:
|
||||
void RegisterLoaders(NameToLoaderMap* name_to_loader_map) override;
|
||||
void RegisterApplicationFactories(ApplicationFactoryMap* factories) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(GpuProcessControlImpl);
|
||||
|
@ -146,8 +146,12 @@ mojo_application_manifest("browser_manifest") {
|
||||
type = "exe"
|
||||
application_name = "content_browser"
|
||||
source = "mojo/content_browser_manifest.json"
|
||||
packaged_applications = [ "user" ]
|
||||
packaged_applications = [
|
||||
"media",
|
||||
"user",
|
||||
]
|
||||
deps = [
|
||||
"//media/mojo/services:media_manifest",
|
||||
"//services/user:manifest",
|
||||
]
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <memory>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "content/common/mojo/static_loader.h"
|
||||
#include "content/public/test/test_mojo_app.h"
|
||||
|
||||
namespace content {
|
||||
|
@ -1,3 +0,0 @@
|
||||
<html>
|
||||
<script src="web_ui_mojo_shell_test.js"></script>
|
||||
</html>
|
@ -1,51 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
|
||||
/**
|
||||
* This URL is defined in content/public/test/test_mojo_app.cc. It identifies
|
||||
* content_shell's out-of-process Mojo test app.
|
||||
*/
|
||||
var TEST_APP_URL = 'system:content_mojo_test';
|
||||
|
||||
|
||||
define('main', [
|
||||
'mojo/public/js/core',
|
||||
'mojo/public/js/router',
|
||||
'services/shell/public/interfaces/connector.mojom',
|
||||
'content/public/renderer/frame_service_registry',
|
||||
'content/public/test/test_mojo_service.mojom',
|
||||
], function (core, router, connectorMojom, serviceRegistry, testMojom) {
|
||||
|
||||
var connectToService = function(serviceProvider, iface) {
|
||||
var pipe = core.createMessagePipe();
|
||||
var service = new iface.proxyClass(new router.Router(pipe.handle0));
|
||||
serviceProvider.getInterface(iface.name, pipe.handle1);
|
||||
return service;
|
||||
};
|
||||
|
||||
return function() {
|
||||
domAutomationController.setAutomationId(0);
|
||||
var connectorPipe =
|
||||
serviceRegistry.connectToService(connectorMojom.Connector.name);
|
||||
var connector = new connectorMojom.Connector.proxyClass(
|
||||
new router.Router(connectorPipe));
|
||||
|
||||
var identity = {};
|
||||
identity.name = TEST_APP_URL;
|
||||
identity.user_id = connectorMojom.kInheritUserID;
|
||||
identity.instance = "";
|
||||
connector.connect(
|
||||
identity,
|
||||
function (services) {
|
||||
var test = connectToService(services, testMojom.TestMojoService);
|
||||
test.getRequestorName().then(function(response) {
|
||||
domAutomationController.send(
|
||||
response.name == 'chrome://mojo-web-ui/');
|
||||
});
|
||||
},
|
||||
function (exposedServices) {},
|
||||
null);
|
||||
};
|
||||
});
|
@ -5,7 +5,6 @@
|
||||
#include "content/utility/utility_process_control_impl.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "content/common/mojo/static_loader.h"
|
||||
#include "content/public/common/content_client.h"
|
||||
#include "content/public/utility/content_utility_client.h"
|
||||
#include "content/public/utility/utility_thread.h"
|
||||
@ -17,37 +16,27 @@
|
||||
|
||||
namespace content {
|
||||
|
||||
namespace {
|
||||
|
||||
// Called when a static application terminates.
|
||||
void QuitProcess() {
|
||||
UtilityThread::Get()->ReleaseProcessIfNeeded();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
UtilityProcessControlImpl::UtilityProcessControlImpl() {}
|
||||
|
||||
UtilityProcessControlImpl::~UtilityProcessControlImpl() {}
|
||||
|
||||
void UtilityProcessControlImpl::RegisterLoaders(
|
||||
NameToLoaderMap* name_to_loader_map) {
|
||||
NameToLoaderMap& map_ref = *name_to_loader_map;
|
||||
|
||||
void UtilityProcessControlImpl::RegisterApplicationFactories(
|
||||
ApplicationFactoryMap* factories) {
|
||||
ContentUtilityClient::StaticMojoApplicationMap apps;
|
||||
GetContentClient()->utility()->RegisterMojoApplications(&apps);
|
||||
|
||||
for (const auto& entry : apps) {
|
||||
map_ref[entry.first] =
|
||||
new StaticLoader(entry.second, base::Bind(&QuitProcess));
|
||||
}
|
||||
for (const auto& entry : apps)
|
||||
factories->insert(std::make_pair(entry.first, entry.second));
|
||||
|
||||
#if defined(ENABLE_MOJO_MEDIA_IN_UTILITY_PROCESS)
|
||||
map_ref["mojo:media"] = new StaticLoader(
|
||||
base::Bind(&media::CreateMojoMediaApplication), base::Bind(&QuitProcess));
|
||||
factories->insert(std::make_pair(
|
||||
"mojo:media", base::Bind(&media::CreateMojoMediaApplication)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void UtilityProcessControlImpl::OnApplicationQuit() {
|
||||
UtilityThread::Get()->ReleaseProcessIfNeeded();
|
||||
}
|
||||
|
||||
void UtilityProcessControlImpl::OnLoadFailed() {
|
||||
UtilityThreadImpl* utility_thread =
|
||||
static_cast<UtilityThreadImpl*>(UtilityThread::Get());
|
||||
|
@ -18,7 +18,8 @@ class UtilityProcessControlImpl : public ProcessControlImpl {
|
||||
~UtilityProcessControlImpl() override;
|
||||
|
||||
// ProcessControlImpl:
|
||||
void RegisterLoaders(NameToLoaderMap* name_to_loader_map) override;
|
||||
void RegisterApplicationFactories(ApplicationFactoryMap* factories) override;
|
||||
void OnApplicationQuit() override;
|
||||
|
||||
private:
|
||||
void OnLoadFailed() override;
|
||||
|
@ -240,6 +240,11 @@ mojo_native_application("media") {
|
||||
]
|
||||
}
|
||||
|
||||
mojo_application_manifest("media_manifest") {
|
||||
application_name = "media"
|
||||
source = "media_manifest.json"
|
||||
}
|
||||
|
||||
# Note, the following tests must be loaded via mojo_runner as an app, e.g.
|
||||
#
|
||||
# mojo/tools/apptest_runner.py
|
||||
|
6
media/mojo/services/media_manifest.json
Normal file
6
media/mojo/services/media_manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "mojo:media",
|
||||
"process-group": "browser",
|
||||
"display_name": "Media Service",
|
||||
"capabilities": { "*": ["*"] }
|
||||
}
|
Reference in New Issue
Block a user