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); |
} |