1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Tests for the --load-and-launch-app switch.
6 // The two cases are when chrome is running and another process uses the switch
7 // and when chrome is started from scratch.
11 #include "apps/switches.h"
12 #include "base/command_line.h"
13 #include "base/containers/contains.h"
14 #include "base/process/launch.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/test/test_switches.h"
17 #include "base/test/test_timeouts.h"
18 #include "build/branding_buildflags.h"
19 #include "build/build_config.h"
20 #include "build/chromeos_buildflags.h"
21 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
22 #include "chrome/browser/extensions/extension_browsertest.h"
23 #include "chrome/browser/extensions/load_error_reporter.h"
24 #include "chrome/browser/profiles/profile_manager.h"
25 #include "chrome/browser/ui/simple_message_box_internal.h"
26 #include "chrome/common/chrome_result_codes.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "content/public/common/content_switches.h"
29 #include "content/public/test/browser_test.h"
30 #include "content/public/test/test_launcher.h"
31 #include "extensions/browser/extension_registry.h"
32 #include "extensions/test/extension_test_message_listener.h"
33 #include "sandbox/policy/switches.h"
35 using extensions::PlatformAppBrowserTest;
41 constexpr char kTestExtensionId[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
43 // Lacros doesn't support launching with chrome already running. See the header
44 // comment for InProcessBrowserTest::GetCommandLineForRelaunch().
45 #if !BUILDFLAG(IS_CHROMEOS_LACROS)
47 const char* const kSwitchesToCopy[] = {
48 sandbox::policy::switches::kNoSandbox,
49 switches::kUserDataDir,
52 // TODO(jackhou): Enable this test once it works on OSX. It currently does not
53 // work for the same reason --app-id doesn't. See http://crbug.com/148465
55 #define MAYBE_LoadAndLaunchAppChromeRunning \
56 DISABLED_LoadAndLaunchAppChromeRunning
58 #define MAYBE_LoadAndLaunchAppChromeRunning LoadAndLaunchAppChromeRunning
61 // Case where Chrome is already running.
62 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
63 MAYBE_LoadAndLaunchAppChromeRunning) {
64 ExtensionTestMessageListener launched_listener("Launched");
66 const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess();
67 base::CommandLine new_cmdline(cmdline.GetProgram());
68 new_cmdline.CopySwitchesFrom(cmdline, kSwitchesToCopy);
70 base::FilePath app_path = test_data_dir_
71 .AppendASCII("platform_apps")
72 .AppendASCII("minimal");
74 new_cmdline.AppendSwitchNative(apps::kLoadAndLaunchApp,
77 new_cmdline.AppendSwitch(switches::kLaunchAsBrowser);
78 base::Process process =
79 base::LaunchProcess(new_cmdline, base::LaunchOptionsForTest());
80 ASSERT_TRUE(process.IsValid());
82 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
84 ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_timeout(),
86 ASSERT_EQ(chrome::RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED, exit_code);
89 // TODO(jackhou): Enable this test once it works on OSX. It currently does not
90 // work for the same reason --app-id doesn't. See http://crbug.com/148465.
92 #define MAYBE_LoadAndLaunchAppWithFile DISABLED_LoadAndLaunchAppWithFile
94 #define MAYBE_LoadAndLaunchAppWithFile LoadAndLaunchAppWithFile
97 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
98 MAYBE_LoadAndLaunchAppWithFile) {
99 ExtensionTestMessageListener launched_listener("Launched");
101 const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess();
102 base::CommandLine new_cmdline(cmdline.GetProgram());
103 new_cmdline.CopySwitchesFrom(cmdline, kSwitchesToCopy);
105 base::FilePath app_path = test_data_dir_
106 .AppendASCII("platform_apps")
107 .AppendASCII("load_and_launch_file");
109 base::FilePath test_file_path = test_data_dir_
110 .AppendASCII("platform_apps")
111 .AppendASCII("launch_files")
112 .AppendASCII("test.txt");
114 new_cmdline.AppendSwitchNative(apps::kLoadAndLaunchApp,
116 new_cmdline.AppendSwitch(switches::kLaunchAsBrowser);
117 new_cmdline.AppendArgPath(test_file_path);
119 base::Process process =
120 base::LaunchProcess(new_cmdline, base::LaunchOptionsForTest());
121 ASSERT_TRUE(process.IsValid());
123 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
125 ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_timeout(),
127 ASSERT_EQ(chrome::RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED, exit_code);
130 #endif // !BUILDFLAG(IS_CHROMEOS_LACROS)
132 // TestFixture that appends --load-and-launch-app with an app before calling
134 class LoadAndLaunchPlatformAppBrowserTest : public PlatformAppBrowserTest {
136 LoadAndLaunchPlatformAppBrowserTest(
137 const LoadAndLaunchPlatformAppBrowserTest&) = delete;
138 LoadAndLaunchPlatformAppBrowserTest& operator=(
139 const LoadAndLaunchPlatformAppBrowserTest&) = delete;
142 LoadAndLaunchPlatformAppBrowserTest() = default;
144 void SetUpCommandLine(base::CommandLine* command_line) override {
145 PlatformAppBrowserTest::SetUpCommandLine(command_line);
146 base::FilePath app_path =
147 test_data_dir_.AppendASCII("platform_apps").AppendASCII("minimal");
148 command_line->AppendSwitchNative(apps::kLoadAndLaunchApp, app_path.value());
150 // |launched_listener_| needs to be instantiated before the app process is
151 // launched to ensure the test api observer is registered.
153 std::make_unique<ExtensionTestMessageListener>("Launched");
156 void TearDownOnMainThread() override { launched_listener_.reset(); }
158 void LoadAndLaunchApp() {
159 ASSERT_TRUE(launched_listener_->WaitUntilSatisfied());
161 // Start an actual browser because we can't shut down with just an app
163 CreateBrowser(profile());
166 std::unique_ptr<ExtensionTestMessageListener> launched_listener_;
169 // TestFixture that appends --load-and-launch-app with an extension before
170 // calling BrowserMain.
171 class LoadAndLaunchExtensionBrowserTest : public PlatformAppBrowserTest {
173 LoadAndLaunchExtensionBrowserTest(const LoadAndLaunchExtensionBrowserTest&) =
175 LoadAndLaunchExtensionBrowserTest& operator=(
176 const LoadAndLaunchExtensionBrowserTest&) = delete;
179 LoadAndLaunchExtensionBrowserTest() = default;
181 void SetUpCommandLine(base::CommandLine* command_line) override {
182 PlatformAppBrowserTest::SetUpCommandLine(command_line);
183 base::FilePath app_path = test_data_dir_.AppendASCII("good")
184 .AppendASCII("Extensions")
185 .AppendASCII(kTestExtensionId)
186 .AppendASCII("1.0.0.0");
187 command_line->AppendSwitchNative(apps::kLoadAndLaunchApp, app_path.value());
190 void SetUpInProcessBrowserTestFixture() override {
191 PlatformAppBrowserTest::SetUpInProcessBrowserTestFixture();
193 // Skip showing the error message box to avoid freezing the main thread.
194 chrome::internal::g_should_skip_message_box_for_test = true;
198 // Case where Chrome is not running.
199 IN_PROC_BROWSER_TEST_F(LoadAndLaunchPlatformAppBrowserTest,
200 LoadAndLaunchAppChromeNotRunning) {
204 IN_PROC_BROWSER_TEST_F(LoadAndLaunchExtensionBrowserTest,
205 LoadAndLaunchExtension) {
206 const std::vector<std::u16string>* errors =
207 extensions::LoadErrorReporter::GetInstance()->GetErrors();
209 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
210 // The error is skipped on official builds.
211 EXPECT_TRUE(errors->empty());
213 // Expect |extension_instead_of_app_error|.
214 EXPECT_EQ(1u, errors->size());
215 EXPECT_TRUE(base::Contains(
216 *errors, u"App loading flags cannot be used to load extensions"));
219 extensions::ExtensionRegistry* registry =
220 extensions::ExtensionRegistry::Get(profile());
222 registry->GetExtensionById(
223 kTestExtensionId, extensions::ExtensionRegistry::EVERYTHING));