| Index: chrome/test/base/mojo_test_connector.cc
|
| diff --git a/chrome/test/base/mojo_test_connector.cc b/chrome/test/base/mojo_test_connector.cc
|
| index 2c7e92ade6b207f95ca9d6f42c1c8347caae0312..2fb999e222f78b811f07d05b8f03d58270f0b70a 100644
|
| --- a/chrome/test/base/mojo_test_connector.cc
|
| +++ b/chrome/test/base/mojo_test_connector.cc
|
| @@ -8,8 +8,6 @@
|
| #include "base/callback.h"
|
| #include "base/command_line.h"
|
| #include "base/memory/ptr_util.h"
|
| -#include "base/memory/weak_ptr.h"
|
| -#include "base/message_loop/message_loop.h"
|
| #include "base/run_loop.h"
|
| #include "base/strings/string_number_conversions.h"
|
| #include "base/synchronization/waitable_event.h"
|
| @@ -18,10 +16,8 @@
|
| #include "content/public/test/test_launcher.h"
|
| #include "mojo/edk/embedder/embedder.h"
|
| #include "mojo/edk/embedder/platform_channel_pair.h"
|
| -#include "mojo/edk/embedder/scoped_ipc_support.h"
|
| #include "mojo/public/cpp/bindings/interface_request.h"
|
| #include "services/catalog/store.h"
|
| -#include "services/service_manager/background/background_service_manager.h"
|
| #include "services/service_manager/public/cpp/connector.h"
|
| #include "services/service_manager/public/cpp/service.h"
|
| #include "services/service_manager/public/cpp/service_context.h"
|
| @@ -36,25 +32,23 @@
|
| const char kTestRunnerName[] = "mash_browser_tests";
|
| const char kTestName[] = "content_browser";
|
|
|
| -// State created per test to register a client process with the background
|
| -// service manager.
|
| -class MojoTestState : public content::TestState {
|
| +// BackgroundTestState maintains all the state necessary to bind the test to
|
| +// mojo. This class is only used on the thread created by
|
| +// BackgroundServiceManager.
|
| +class BackgroundTestState {
|
| public:
|
| - explicit MojoTestState(
|
| - service_manager::BackgroundServiceManager* background_service_manager)
|
| - : child_token_(mojo::edk::GenerateRandomToken()),
|
| - background_service_manager_(background_service_manager),
|
| - weak_factory_(this) {}
|
| - ~MojoTestState() override {}
|
| -
|
| - void Init(base::CommandLine* command_line,
|
| - base::TestLauncher::LaunchOptions* test_launch_options) {
|
| + BackgroundTestState() : child_token_(mojo::edk::GenerateRandomToken()) {}
|
| + ~BackgroundTestState() {}
|
| +
|
| + // Prepares the command line and other setup for connecting the test to mojo.
|
| + // Must be paired with a call to ChildProcessLaunched().
|
| + void Connect(base::CommandLine* command_line,
|
| + service_manager::ServiceManager* service_manager,
|
| + base::TestLauncher::LaunchOptions* test_launch_options) {
|
| command_line->AppendSwitch(MojoTestConnector::kTestSwitch);
|
| command_line->AppendSwitch(switches::kChildProcess);
|
| -
|
| - platform_channel_ = base::MakeUnique<mojo::edk::PlatformChannelPair>();
|
| -
|
| - platform_channel_->PrepareToPassClientHandleToChildProcess(
|
| + mojo_ipc_channel_.reset(new mojo::edk::PlatformChannelPair);
|
| + mojo_ipc_channel_->PrepareToPassClientHandleToChildProcess(
|
| command_line, &handle_passing_info_);
|
| #if defined(OS_WIN)
|
| test_launch_options->inherit_handles = true;
|
| @@ -71,49 +65,115 @@
|
| service_manager::PassServiceRequestOnCommandLine(command_line,
|
| child_token_);
|
|
|
| - background_service_manager_->RegisterService(
|
| - service_manager::Identity(
|
| - kTestName, service_manager::mojom::kRootUserID),
|
| - std::move(service),
|
| - service_manager::mojom::PIDReceiverRequest(&pid_receiver_));
|
| -
|
| - // ChildProcessLaunched may be called on an arbitrary thread, so track the
|
| - // current TaskRunner and post back to it when we want to send the PID.
|
| - main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
| + std::unique_ptr<service_manager::ConnectParams> params(
|
| + new service_manager::ConnectParams);
|
| + params->set_source(service_manager::CreateServiceManagerIdentity());
|
| + // Use the default instance name (which should be "browser"). Otherwise a
|
| + // service (e.g. ash) that connects to the default "content_browser"
|
| + // will spawn a new instance.
|
| + params->set_target(service_manager::Identity(
|
| + kTestName, service_manager::mojom::kRootUserID));
|
| + params->set_client_process_info(std::move(service),
|
| + MakeRequest(&pid_receiver_));
|
| + service_manager->Connect(std::move(params));
|
| + }
|
| +
|
| + // Called after the test process has launched. Completes the registration done
|
| + // in Connect().
|
| + void ChildProcessLaunched(base::ProcessHandle handle, base::ProcessId pid) {
|
| + pid_receiver_->SetPID(pid);
|
| + mojo_ipc_channel_->ChildProcessLaunched();
|
| + mojo::edk::ChildProcessLaunched(
|
| + handle, mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(
|
| + mojo_ipc_channel_->PassServerHandle().release().handle)),
|
| + child_token_);
|
| + }
|
| +
|
| + private:
|
| + // Used to back the NodeChannel between the parent and child node.
|
| + const std::string child_token_;
|
| + std::unique_ptr<mojo::edk::PlatformChannelPair> mojo_ipc_channel_;
|
| +
|
| + mojo::edk::HandlePassingInformation handle_passing_info_;
|
| +
|
| + service_manager::mojom::PIDReceiverPtr pid_receiver_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(BackgroundTestState);
|
| +};
|
| +
|
| +// Called used destroy BackgroundTestState on the background thread.
|
| +void DestroyBackgroundStateOnBackgroundThread(
|
| + std::unique_ptr<BackgroundTestState> state,
|
| + service_manager::ServiceManager* service_manager) {}
|
| +
|
| +// State created per test. Manages creation of the corresponding
|
| +// BackgroundTestState and making sure processing runs on the right threads.
|
| +class MojoTestState : public content::TestState {
|
| + public:
|
| + explicit MojoTestState(
|
| + service_manager::BackgroundServiceManager* background_service_manager)
|
| + : background_service_manager_(background_service_manager) {}
|
| +
|
| + ~MojoTestState() override {
|
| + DCHECK(background_state_);
|
| + // BackgroundState needs to be destroyed on the background thread. We're
|
| + // guaranteed |background_service_manager_| has been created by the time we
|
| + // reach
|
| + // here as Init() blocks until |background_service_manager_| has been
|
| + // created.
|
| + background_service_manager_->ExecuteOnServiceManagerThread(
|
| + base::Bind(&DestroyBackgroundStateOnBackgroundThread,
|
| + base::Passed(&background_state_)));
|
| + }
|
| +
|
| + void Init(base::CommandLine* command_line,
|
| + base::TestLauncher::LaunchOptions* test_launch_options) {
|
| + base::WaitableEvent signal(base::WaitableEvent::ResetPolicy::MANUAL,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| + background_service_manager_->ExecuteOnServiceManagerThread(base::Bind(
|
| + &MojoTestState::BindOnBackgroundThread, base::Unretained(this), &signal,
|
| + command_line, test_launch_options));
|
| + signal.Wait();
|
| }
|
|
|
| private:
|
| // content::TestState:
|
| void ChildProcessLaunched(base::ProcessHandle handle,
|
| base::ProcessId pid) override {
|
| - platform_channel_->ChildProcessLaunched();
|
| - mojo::edk::ChildProcessLaunched(
|
| - handle, platform_channel_->PassServerHandle(), child_token_);
|
| -
|
| - main_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&MojoTestState::SetPID, weak_factory_.GetWeakPtr(), pid));
|
| - }
|
| -
|
| - // Called on the main thread only.
|
| - void SetPID(base::ProcessId pid) {
|
| - DCHECK(pid_receiver_.is_bound());
|
| - pid_receiver_->SetPID(pid);
|
| - pid_receiver_.reset();
|
| - }
|
| -
|
| - const std::string child_token_;
|
| - service_manager::BackgroundServiceManager* const background_service_manager_;
|
| -
|
| - // NOTE: HandlePassingInformation must remain valid through process launch,
|
| - // hence it lives here instead of within Init()'s stack.
|
| - mojo::edk::HandlePassingInformation handle_passing_info_;
|
| -
|
| - std::unique_ptr<mojo::edk::PlatformChannelPair> platform_channel_;
|
| - service_manager::mojom::PIDReceiverPtr pid_receiver_;
|
| - scoped_refptr<base::TaskRunner> main_task_runner_ = nullptr;
|
| -
|
| - base::WeakPtrFactory<MojoTestState> weak_factory_;
|
| + // This is called on a random thread. We need to ensure BackgroundTestState
|
| + // is only called on the background thread, and we wait for
|
| + // ChildProcessLaunchedOnBackgroundThread() to be run before continuing so
|
| + // that |handle| is still valid.
|
| + base::WaitableEvent signal(base::WaitableEvent::ResetPolicy::MANUAL,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| + background_service_manager_->ExecuteOnServiceManagerThread(
|
| + base::Bind(&MojoTestState::ChildProcessLaunchedOnBackgroundThread,
|
| + base::Unretained(this), handle, pid, &signal));
|
| + signal.Wait();
|
| + }
|
| +
|
| + void ChildProcessLaunchedOnBackgroundThread(
|
| + base::ProcessHandle handle,
|
| + base::ProcessId pid,
|
| + base::WaitableEvent* signal,
|
| + service_manager::ServiceManager* service_manager) {
|
| + background_state_->ChildProcessLaunched(handle, pid);
|
| + signal->Signal();
|
| + }
|
| +
|
| + void BindOnBackgroundThread(
|
| + base::WaitableEvent* signal,
|
| + base::CommandLine* command_line,
|
| + base::TestLauncher::LaunchOptions* test_launch_options,
|
| + service_manager::ServiceManager* service_manager) {
|
| + background_state_.reset(new BackgroundTestState);
|
| + background_state_->Connect(command_line, service_manager,
|
| + test_launch_options);
|
| + signal->Signal();
|
| + }
|
| +
|
| + service_manager::BackgroundServiceManager* background_service_manager_;
|
| + std::unique_ptr<BackgroundTestState> background_state_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(MojoTestState);
|
| };
|
| @@ -171,34 +231,22 @@
|
| // static
|
| const char MojoTestConnector::kMashApp[] = "mash-app";
|
|
|
| -MojoTestConnector::MojoTestConnector(
|
| - std::unique_ptr<base::Value> catalog_contents)
|
| - : service_process_launcher_delegate_(
|
| - new ServiceProcessLauncherDelegateImpl),
|
| - background_service_manager_(service_process_launcher_delegate_.get(),
|
| - std::move(catalog_contents)) {}
|
| +MojoTestConnector::MojoTestConnector() {}
|
|
|
| service_manager::mojom::ServiceRequest MojoTestConnector::Init() {
|
| - // In single-process test mode, browser code will initialize the EDK and IPC.
|
| - // Otherwise we ensure it's initialized here.
|
| - if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| - content::kSingleProcessTestsFlag)) {
|
| - mojo::edk::Init();
|
| - ipc_thread_ = base::MakeUnique<base::Thread>("IPC thread");
|
| - ipc_thread_->StartWithOptions(base::Thread::Options(
|
| - base::MessageLoop::TYPE_IO, 0));
|
| - ipc_support_ = base::MakeUnique<mojo::edk::ScopedIPCSupport>(
|
| - ipc_thread_->task_runner(),
|
| - mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST);
|
| - }
|
| -
|
| - service_manager::mojom::ServicePtr service;
|
| - service_manager::mojom::ServiceRequest request(&service);
|
| - background_service_manager_.RegisterService(
|
| - service_manager::Identity(kTestRunnerName,
|
| - service_manager::mojom::kRootUserID),
|
| - std::move(service), nullptr);
|
| - return request;
|
| + service_process_launcher_delegate_ =
|
| + base::MakeUnique<ServiceProcessLauncherDelegateImpl>();
|
| +
|
| + std::unique_ptr<service_manager::BackgroundServiceManager::InitParams>
|
| + init_params = base::MakeUnique<
|
| + service_manager::BackgroundServiceManager::InitParams>();
|
| + // When running in single_process mode chrome initializes the edk.
|
| + init_params->init_edk = !base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| + content::kSingleProcessTestsFlag);
|
| + init_params->service_process_launcher_delegate =
|
| + service_process_launcher_delegate_.get();
|
| + background_service_manager_.Init(std::move(init_params));
|
| + return background_service_manager_.CreateServiceRequest(kTestRunnerName);
|
| }
|
|
|
| MojoTestConnector::~MojoTestConnector() {}
|
| @@ -206,8 +254,8 @@
|
| std::unique_ptr<content::TestState> MojoTestConnector::PrepareForTest(
|
| base::CommandLine* command_line,
|
| base::TestLauncher::LaunchOptions* test_launch_options) {
|
| - auto test_state =
|
| - base::MakeUnique<MojoTestState>(&background_service_manager_);
|
| + std::unique_ptr<MojoTestState> test_state(
|
| + new MojoTestState(&background_service_manager_));
|
| test_state->Init(command_line, test_launch_options);
|
| - return test_state;
|
| + return std::move(test_state);
|
| }
|
|
|