0

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:
rockot
2016-04-15 14:46:20 -07:00
committed by Commit bot
parent 8e9314bcf3
commit 3cc6df2e0b
24 changed files with 218 additions and 440 deletions

@ -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

@ -0,0 +1,6 @@
{
"name": "mojo:media",
"process-group": "browser",
"display_name": "Media Service",
"capabilities": { "*": ["*"] }
}