Fix mojo::shell::Context shutdown.
Make shutdown explicit (i.e., if you call Init(), you have to call
Shutdown()).
R=jamesr@chromium.org
Review URL: https://codereview.chromium.org/939353002
diff --git a/shell/child_process_host_unittest.cc b/shell/child_process_host_unittest.cc
index 6aa77b4..c52c8c7 100644
--- a/shell/child_process_host_unittest.cc
+++ b/shell/child_process_host_unittest.cc
@@ -52,6 +52,8 @@
int exit_code = child_process_host.Join();
VLOG(2) << "Joined child: exit_code = " << exit_code;
EXPECT_EQ(0, exit_code);
+
+ context.Shutdown();
}
} // namespace
diff --git a/shell/context.cc b/shell/context.cc
index 0707cef..c3efa89 100644
--- a/shell/context.cc
+++ b/shell/context.cc
@@ -15,6 +15,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/path_service.h"
+#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
@@ -55,8 +56,6 @@
DISALLOW_COPY_AND_ASSIGN(Setup);
};
-static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER;
-
void InitContentHandlers(NativeApplicationLoader* loader,
base::CommandLine* command_line) {
// Default content handlers.
@@ -194,7 +193,9 @@
DCHECK(!base::MessageLoop::current());
}
+// static
void Context::EnsureEmbedderIsInitialized() {
+ static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER;
setup.Get();
}
@@ -276,14 +277,21 @@
}
void Context::Shutdown() {
+ DCHECK_EQ(base::MessageLoop::current()->task_runner(),
+ task_runners_->shell_runner());
embedder::ShutdownIPCSupport();
+ // We'll quit when we get OnShutdownComplete().
+ base::MessageLoop::current()->Run();
}
void Context::OnApplicationError(const GURL& url) {
if (app_urls_.find(url) != app_urls_.end()) {
app_urls_.erase(url);
- if (app_urls_.empty() && base::MessageLoop::current()->is_running())
- Shutdown();
+ if (app_urls_.empty() && base::MessageLoop::current()->is_running()) {
+ DCHECK_EQ(base::MessageLoop::current()->task_runner(),
+ task_runners_->shell_runner());
+ base::MessageLoop::current()->Quit();
+ }
}
}
diff --git a/shell/context.h b/shell/context.h
index 4d2cf34..62c49c2 100644
--- a/shell/context.h
+++ b/shell/context.h
@@ -26,6 +26,8 @@
Context();
~Context() override;
+ static void EnsureEmbedderIsInitialized();
+
// Point to the directory containing installed services, such as the network
// service. By default this directory is used as the base URL for resolving
// unknown mojo: URLs. The network service will be loaded from this directory,
@@ -44,9 +46,14 @@
// nop for everything but relative file URLs or URLs without a scheme.
GURL ResolveCommandLineURL(const std::string& path);
- static void EnsureEmbedderIsInitialized();
+ // This must be called with a message loop set up for the current thread,
+ // which must remain alive until after Shutdown() is called. Returns true on
+ // success.
bool Init();
+ // If Init() was called and succeeded, this must be called before destruction.
+ void Shutdown();
+
void Run(const GURL& url);
ScopedMessagePipeHandle ConnectToServiceByName(
const GURL& application_url,
@@ -59,8 +66,6 @@
private:
class NativeViewportApplicationLoader;
- void Shutdown();
-
// ApplicationManager::Delegate overrides.
void OnApplicationError(const GURL& url) override;
GURL ResolveURL(const GURL& url) override;
diff --git a/shell/desktop/mojo_main.cc b/shell/desktop/mojo_main.cc
index 8989b9e..d8ac657 100644
--- a/shell/desktop/mojo_main.cc
+++ b/shell/desktop/mojo_main.cc
@@ -108,6 +108,9 @@
FROM_HERE,
base::Bind(&mojo::shell::RunCommandLineApps, &shell_context));
message_loop.Run();
+
+ // Must be called be |message_loop| is destroyed.
+ shell_context.Shutdown();
}
}
return 0;
diff --git a/shell/in_process_dynamic_service_runner_unittest.cc b/shell/in_process_dynamic_service_runner_unittest.cc
index a2ff900..d0c81ae 100644
--- a/shell/in_process_dynamic_service_runner_unittest.cc
+++ b/shell/in_process_dynamic_service_runner_unittest.cc
@@ -14,6 +14,7 @@
base::MessageLoop loop;
context.Init();
InProcessDynamicServiceRunner runner(&context);
+ context.Shutdown();
// Shouldn't crash or DCHECK on destruction.
}
diff --git a/shell/native_application_loader_unittest.cc b/shell/native_application_loader_unittest.cc
index 473412a..697f828 100644
--- a/shell/native_application_loader_unittest.cc
+++ b/shell/native_application_loader_unittest.cc
@@ -70,6 +70,7 @@
new TestDynamicServiceRunnerFactory(&state_));
loader_.reset(new NativeApplicationLoader(&context_, factory.Pass()));
}
+ void TearDown() override { context_.Shutdown(); }
protected:
Context context_;
diff --git a/shell/shell_test_base.cc b/shell/shell_test_base.cc
index 6e4f18c..20e6b35 100644
--- a/shell/shell_test_base.cc
+++ b/shell/shell_test_base.cc
@@ -24,10 +24,14 @@
}
void ShellTestBase::SetUp() {
- shell_context_.Init();
+ CHECK(shell_context_.Init());
SetUpTestApplications();
}
+void ShellTestBase::TearDown() {
+ shell_context_.Shutdown();
+}
+
ScopedMessagePipeHandle ShellTestBase::ConnectToService(
const GURL& application_url,
const std::string& service_name) {
diff --git a/shell/shell_test_base.h b/shell/shell_test_base.h
index 2679bb5..bfb320b 100644
--- a/shell/shell_test_base.h
+++ b/shell/shell_test_base.h
@@ -25,6 +25,7 @@
~ShellTestBase() override;
void SetUp() override;
+ void TearDown() override;
// |application_url| should typically be a mojo: URL (the origin will be set
// to an "appropriate" file: URL).