1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <map>
6
7 #include "base/strings/stringprintf.h"
8 #include "build/build_config.h"
9 #include "chrome/browser/extensions/extension_apitest.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/launch_util.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_commands.h"
15 #include "chrome/browser/ui/browser_dialogs.h"
16 #include "chrome/browser/ui/browser_finder.h"
17 #include "chrome/browser/ui/browser_list.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/browser/web_applications/components/app_registrar.h"
20 #include "chrome/browser/web_applications/components/app_shortcut_manager.h"
21 #include "chrome/browser/web_applications/components/web_app_helpers.h"
22 #include "chrome/browser/web_applications/components/web_app_provider_base.h"
23 #include "chrome/browser/web_applications/test/test_web_app_ui_manager.h"
24 #include "chrome/browser/web_applications/test/web_app_test.h"
25 #include "chrome/common/chrome_features.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/extensions/extension_constants.h"
28 #include "extensions/browser/api/management/management_api.h"
29 #include "extensions/browser/extension_dialog_auto_confirm.h"
30 #include "extensions/browser/extension_registry.h"
31 #include "extensions/browser/extension_system.h"
32 #include "extensions/browser/test_management_policy.h"
33 #include "extensions/common/manifest.h"
34 #include "extensions/test/extension_test_message_listener.h"
35 #include "extensions/test/result_catcher.h"
36 #include "extensions/test/test_extension_dir.h"
37 #include "net/dns/mock_host_resolver.h"
38
39 using extensions::Extension;
40 using extensions::Manifest;
41 using web_app::ProviderType;
42
43 namespace {
44
45 // Find a browser other than |browser|.
FindOtherBrowser(Browser * browser)46 Browser* FindOtherBrowser(Browser* browser) {
47 Browser* found = NULL;
48 for (auto* b : *BrowserList::GetInstance()) {
49 if (b == browser)
50 continue;
51 found = b;
52 }
53 return found;
54 }
55
56 } // namespace
57
58 class ExtensionManagementApiTest : public extensions::ExtensionApiTest {
59 public:
LoadExtensions()60 virtual void LoadExtensions() {
61 base::FilePath basedir = test_data_dir_.AppendASCII("management");
62
63 // Load 5 enabled items.
64 LoadNamedExtension(basedir, "enabled_extension");
65 LoadNamedExtension(basedir, "enabled_app");
66 LoadNamedExtension(basedir, "description");
67 LoadNamedExtension(basedir, "permissions");
68 LoadNamedExtension(basedir, "short_name");
69
70 // Load 2 disabled items.
71 LoadNamedExtension(basedir, "disabled_extension");
72 DisableExtension(extension_ids_["disabled_extension"]);
73 LoadNamedExtension(basedir, "disabled_app");
74 DisableExtension(extension_ids_["disabled_app"]);
75 }
76
77 // Load an app, and wait for a message that it has been launched. This should
78 // be sent by the launched app, to ensure the page is fully loaded.
LoadAndWaitForLaunch(const std::string & app_path,std::string * out_app_id)79 void LoadAndWaitForLaunch(const std::string& app_path,
80 std::string* out_app_id) {
81 ExtensionTestMessageListener launched_app("launched app", false);
82 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(app_path)));
83
84 if (out_app_id)
85 *out_app_id = last_loaded_extension_id();
86
87 ASSERT_TRUE(launched_app.WaitUntilSatisfied());
88 }
89
90 protected:
LoadNamedExtension(const base::FilePath & path,const std::string & name)91 void LoadNamedExtension(const base::FilePath& path,
92 const std::string& name) {
93 const Extension* extension = LoadExtension(path.AppendASCII(name));
94 ASSERT_TRUE(extension);
95 extension_ids_[name] = extension->id();
96 }
97
InstallNamedExtension(const base::FilePath & path,const std::string & name,Manifest::Location install_source)98 void InstallNamedExtension(const base::FilePath& path,
99 const std::string& name,
100 Manifest::Location install_source) {
101 const Extension* extension = InstallExtension(path.AppendASCII(name), 1,
102 install_source);
103 ASSERT_TRUE(extension);
104 extension_ids_[name] = extension->id();
105 }
106
107 // Maps installed extension names to their IDs.
108 std::map<std::string, std::string> extension_ids_;
109 };
110
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,Basics)111 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, Basics) {
112 LoadExtensions();
113
114 base::FilePath basedir = test_data_dir_.AppendASCII("management");
115 InstallNamedExtension(basedir, "internal_extension", Manifest::INTERNAL);
116 InstallNamedExtension(basedir, "external_extension",
117 Manifest::EXTERNAL_PREF);
118 InstallNamedExtension(basedir, "admin_extension",
119 Manifest::EXTERNAL_POLICY_DOWNLOAD);
120 InstallNamedExtension(basedir, "version_name", Manifest::INTERNAL);
121
122 ASSERT_TRUE(RunExtensionSubtest("management/test", "basics.html"));
123 }
124
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,NoPermission)125 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, NoPermission) {
126 LoadExtensions();
127 ASSERT_TRUE(RunExtensionSubtest("management/no_permission", "test.html"));
128 }
129
130 // Disabled: http://crbug.com/174411
131 #if defined(OS_WIN)
132 #define MAYBE_Uninstall DISABLED_Uninstall
133 #else
134 #define MAYBE_Uninstall Uninstall
135 #endif
136
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,MAYBE_Uninstall)137 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, MAYBE_Uninstall) {
138 LoadExtensions();
139 // Confirmation dialog will be shown for uninstallations except for self.
140 extensions::ScopedTestDialogAutoConfirm auto_confirm(
141 extensions::ScopedTestDialogAutoConfirm::ACCEPT);
142 ASSERT_TRUE(RunExtensionSubtest("management/test", "uninstall.html"));
143 }
144
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,CreateAppShortcut)145 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, CreateAppShortcut) {
146 LoadExtensions();
147 base::FilePath basedir = test_data_dir_.AppendASCII("management");
148 LoadNamedExtension(basedir, "packaged_app");
149
150 extensions::ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(true);
151 ASSERT_TRUE(RunExtensionSubtest("management/test",
152 "createAppShortcut.html"));
153 }
154
155 class GenerateAppManagementApiTest
156 : public ExtensionManagementApiTest,
157 public ::testing::WithParamInterface<ProviderType> {
158 public:
SetUp()159 void SetUp() override {
160 if (GetParam() == ProviderType::kWebApps) {
161 scoped_feature_list_.InitWithFeatures(
162 {features::kDesktopPWAsWithoutExtensions}, {});
163 } else {
164 DCHECK_EQ(GetParam(), ProviderType::kBookmarkApps);
165 scoped_feature_list_.InitWithFeatures(
166 {}, {features::kDesktopPWAsWithoutExtensions});
167 }
168
169 ExtensionManagementApiTest::SetUp();
170 }
171
172 private:
173 base::test::ScopedFeatureList scoped_feature_list_;
174 };
175
IN_PROC_BROWSER_TEST_P(GenerateAppManagementApiTest,GenerateAppForLink)176 IN_PROC_BROWSER_TEST_P(GenerateAppManagementApiTest, GenerateAppForLink) {
177 ASSERT_TRUE(RunExtensionSubtest("management/test",
178 "generateAppForLink.html"));
179 }
180
181 INSTANTIATE_TEST_SUITE_P(All,
182 GenerateAppManagementApiTest,
183 ::testing::Values(ProviderType::kBookmarkApps,
184 ProviderType::kWebApps),
185 web_app::ProviderTypeParamToString);
186
187 class InstallReplacementWebAppApiTest : public ExtensionManagementApiTest {
188 public:
InstallReplacementWebAppApiTest()189 InstallReplacementWebAppApiTest()
190 : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
191 ~InstallReplacementWebAppApiTest() override = default;
192
193 protected:
194 static const char kManifest[];
195 static const char kAppManifest[];
196
SetUpOnMainThread()197 void SetUpOnMainThread() override {
198 ExtensionManagementApiTest::SetUpOnMainThread();
199 https_test_server_.ServeFilesFromDirectory(test_data_dir_);
200 ASSERT_TRUE(https_test_server_.Start());
201
202 web_app::WebAppProviderBase::GetProviderBase(profile())
203 ->shortcut_manager()
204 .SuppressShortcutsForTesting();
205 }
206
RunTest(const char * manifest,const char * web_app_path,const char * background_script,bool from_webstore)207 void RunTest(const char* manifest,
208 const char* web_app_path,
209 const char* background_script,
210 bool from_webstore) {
211 extensions::TestExtensionDir extension_dir;
212 extension_dir.WriteManifest(base::StringPrintf(
213 manifest, https_test_server_.GetURL(web_app_path).spec().c_str()));
214 extension_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
215 background_script);
216 extensions::ResultCatcher catcher;
217 if (from_webstore) {
218 // |expected_change| is the expected change in the number of installed
219 // extensions.
220 ASSERT_TRUE(InstallExtensionFromWebstore(extension_dir.UnpackedPath(),
221 1 /* expected_change */));
222 } else {
223 ASSERT_TRUE(LoadExtension(extension_dir.UnpackedPath()));
224 }
225
226 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
227 }
228
RunInstallableWebAppTest(const char * manifest,const char * web_app_url,const char * web_app_start_url)229 void RunInstallableWebAppTest(const char* manifest,
230 const char* web_app_url,
231 const char* web_app_start_url) {
232 static constexpr char kInstallReplacementWebApp[] =
233 R"(chrome.test.runWithUserGesture(function() {
234 chrome.management.installReplacementWebApp(function() {
235 chrome.test.assertNoLastError();
236 chrome.test.notifyPass();
237 });
238 });)";
239
240 chrome::SetAutoAcceptPWAInstallConfirmationForTesting(true);
241 const GURL start_url = https_test_server_.GetURL(web_app_start_url);
242 web_app::AppId web_app_id = web_app::GenerateAppIdFromURL(start_url);
243
244 auto* provider =
245 web_app::WebAppProviderBase::GetProviderBase(browser()->profile());
246 EXPECT_FALSE(provider->registrar().IsLocallyInstalled(start_url));
247 EXPECT_EQ(0, static_cast<int>(
248 provider->ui_manager().GetNumWindowsForApp(web_app_id)));
249
250 RunTest(manifest, web_app_url, kInstallReplacementWebApp,
251 true /* from_webstore */);
252 EXPECT_TRUE(provider->registrar().IsLocallyInstalled(start_url));
253 EXPECT_EQ(1, static_cast<int>(
254 provider->ui_manager().GetNumWindowsForApp(web_app_id)));
255
256 // Call API again. It should launch the app.
257 RunTest(manifest, web_app_url, kInstallReplacementWebApp,
258 true /* from_webstore */);
259 EXPECT_TRUE(provider->registrar().IsLocallyInstalled(start_url));
260 EXPECT_EQ(2, static_cast<int>(
261 provider->ui_manager().GetNumWindowsForApp(web_app_id)));
262
263 chrome::SetAutoAcceptPWAInstallConfirmationForTesting(false);
264 }
265
266 net::EmbeddedTestServer https_test_server_;
267 };
268
269 const char InstallReplacementWebAppApiTest::kManifest[] =
270 R"({
271 "name": "Management API Test",
272 "version": "0.1",
273 "manifest_version": 2,
274 "background": { "scripts": ["background.js"] },
275 "replacement_web_app": "%s"
276 })";
277
278 const char InstallReplacementWebAppApiTest::kAppManifest[] =
279 R"({
280 "name": "Management API Test",
281 "version": "0.1",
282 "manifest_version": 2,
283 "app": {
284 "background": { "scripts": ["background.js"] }
285 },
286 "replacement_web_app": "%s"
287 })";
288
IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,NotWebstore)289 IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest, NotWebstore) {
290 static constexpr char kBackground[] = R"(
291 chrome.management.installReplacementWebApp(function() {
292 chrome.test.assertLastError(
293 'Only extensions from the web store can install replacement web apps.');
294 chrome.test.notifyPass();
295 });)";
296
297 RunTest(kManifest,
298 "/management/install_replacement_web_app/good_web_app/index.html",
299 kBackground, false /* from_webstore */);
300 }
301
IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,NoGesture)302 IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest, NoGesture) {
303 static constexpr char kBackground[] = R"(
304 chrome.management.installReplacementWebApp(function() {
305 chrome.test.assertLastError(
306 'chrome.management.installReplacementWebApp requires a user gesture.');
307 chrome.test.notifyPass();
308 });)";
309
310 RunTest(kManifest,
311 "/management/install_replacement_web_app/good_web_app/index.html",
312 kBackground, true /* from_webstore */);
313 }
314
IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,NotInstallableWebApp)315 IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest, NotInstallableWebApp) {
316 static constexpr char kBackground[] =
317 R"(chrome.test.runWithUserGesture(function() {
318 chrome.management.installReplacementWebApp(function() {
319 chrome.test.assertLastError(
320 'Web app is not a valid installable web app.');
321 chrome.test.notifyPass();
322 });
323 });)";
324
325 RunTest(kManifest,
326 "/management/install_replacement_web_app/bad_web_app/index.html",
327 kBackground, true /* from_webstore */);
328 }
329
IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,InstallableWebApp)330 IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest, InstallableWebApp) {
331 static constexpr char kGoodWebAppURL[] =
332 "/management/install_replacement_web_app/good_web_app/index.html";
333
334 RunInstallableWebAppTest(kManifest, kGoodWebAppURL, kGoodWebAppURL);
335 }
336
337 // Check that web app still installs and launches correctly when start_url does
338 // not match replacement_web_app_url.
IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,InstallableWebAppWithStartUrl)339 IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,
340 InstallableWebAppWithStartUrl) {
341 static constexpr char kGoodWebAppUrl[] =
342 "/management/install_replacement_web_app/good_web_app_with_start_url/"
343 "index.html";
344 static constexpr char kGoodWebAppStartUrl[] =
345 "/management/install_replacement_web_app/good_web_app_with_start_url/"
346 "pwa_start_url.html";
347
348 RunInstallableWebAppTest(kManifest, kGoodWebAppUrl, kGoodWebAppStartUrl);
349 }
350
IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,InstallableWebAppInPlatformApp)351 IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,
352 InstallableWebAppInPlatformApp) {
353 static constexpr char kGoodWebAppURL[] =
354 "/management/install_replacement_web_app/good_web_app/index.html";
355
356 RunInstallableWebAppTest(kAppManifest, kGoodWebAppURL, kGoodWebAppURL);
357 }
358
359 // Fails often on Windows dbg bots. http://crbug.com/177163
360 #if defined(OS_WIN)
361 #define MAYBE_ManagementPolicyAllowed DISABLED_ManagementPolicyAllowed
362 #else
363 #define MAYBE_ManagementPolicyAllowed ManagementPolicyAllowed
364 #endif // defined(OS_WIN)
365 // Tests actions on extensions when no management policy is in place.
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,MAYBE_ManagementPolicyAllowed)366 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,
367 MAYBE_ManagementPolicyAllowed) {
368 LoadExtensions();
369 extensions::ScopedTestDialogAutoConfirm auto_confirm(
370 extensions::ScopedTestDialogAutoConfirm::ACCEPT);
371 extensions::ExtensionRegistry* registry =
372 extensions::ExtensionRegistry::Get(browser()->profile());
373 EXPECT_TRUE(registry->enabled_extensions().GetByID(
374 extension_ids_["enabled_extension"]));
375
376 // Ensure that all actions are allowed.
377 extensions::ExtensionSystem::Get(
378 browser()->profile())->management_policy()->UnregisterAllProviders();
379
380 ASSERT_TRUE(RunExtensionSubtest("management/management_policy",
381 "allowed.html"));
382 // The last thing the test does is uninstall the "enabled_extension".
383 EXPECT_FALSE(
384 registry->GetExtensionById(extension_ids_["enabled_extension"],
385 extensions::ExtensionRegistry::EVERYTHING));
386 }
387
388 // Fails often on Windows dbg bots. http://crbug.com/177163
389 #if defined(OS_WIN)
390 #define MAYBE_ManagementPolicyProhibited DISABLED_ManagementPolicyProhibited
391 #else
392 #define MAYBE_ManagementPolicyProhibited ManagementPolicyProhibited
393 #endif // defined(OS_WIN)
394 // Tests actions on extensions when management policy prohibits those actions.
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,MAYBE_ManagementPolicyProhibited)395 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,
396 MAYBE_ManagementPolicyProhibited) {
397 LoadExtensions();
398 extensions::ExtensionRegistry* registry =
399 extensions::ExtensionRegistry::Get(browser()->profile());
400 EXPECT_TRUE(registry->enabled_extensions().GetByID(
401 extension_ids_["enabled_extension"]));
402
403 // Prohibit status changes.
404 extensions::ManagementPolicy* policy = extensions::ExtensionSystem::Get(
405 browser()->profile())->management_policy();
406 policy->UnregisterAllProviders();
407 extensions::TestManagementPolicyProvider provider(
408 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS |
409 extensions::TestManagementPolicyProvider::MUST_REMAIN_ENABLED |
410 extensions::TestManagementPolicyProvider::MUST_REMAIN_INSTALLED);
411 policy->RegisterProvider(&provider);
412 ASSERT_TRUE(RunExtensionSubtest("management/management_policy",
413 "prohibited.html"));
414 }
415
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,LaunchPanelApp)416 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, LaunchPanelApp) {
417 // Load an extension that calls launchApp() on any app that gets
418 // installed.
419 ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
420 ASSERT_TRUE(LoadExtension(
421 test_data_dir_.AppendASCII("management/launch_on_install")));
422 ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
423
424 // Load an app with app.launch.container = "panel".
425 std::string app_id;
426 LoadAndWaitForLaunch("management/launch_app_panel", &app_id);
427 ASSERT_FALSE(HasFatalFailure()); // Stop the test if any ASSERT failed.
428
429 // Find the app's browser. Check that it is a popup.
430 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
431 Browser* app_browser = FindOtherBrowser(browser());
432 ASSERT_TRUE(app_browser->is_type_app());
433
434 // Close the app panel.
435 CloseBrowserSynchronously(app_browser);
436
437 extensions::ExtensionRegistry* registry =
438 extensions::ExtensionRegistry::Get(browser()->profile());
439 // Unload the extension.
440 UninstallExtension(app_id);
441 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
442 ASSERT_FALSE(registry->GetExtensionById(
443 app_id, extensions::ExtensionRegistry::EVERYTHING));
444
445 // Set a pref indicating that the user wants to launch in a regular tab.
446 // This should be ignored, because panel apps always load in a popup.
447 extensions::SetLaunchType(browser()->profile(), app_id,
448 extensions::LAUNCH_TYPE_REGULAR);
449
450 // Load the extension again.
451 std::string app_id_new;
452 LoadAndWaitForLaunch("management/launch_app_panel", &app_id_new);
453 ASSERT_FALSE(HasFatalFailure());
454
455 // If the ID changed, then the pref will not apply to the app.
456 ASSERT_EQ(app_id, app_id_new);
457
458 // Find the app's browser. Apps that should load in a panel ignore
459 // prefs, so we should still see the launch in a popup.
460 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
461 app_browser = FindOtherBrowser(browser());
462 ASSERT_TRUE(app_browser->is_type_app());
463 }
464
465 // Disabled: crbug.com/230165, crbug.com/915339, crbug.com/979399
466 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
467 defined(OS_CHROMEOS)
468 #define MAYBE_LaunchTabApp DISABLED_LaunchTabApp
469 #else
470 #define MAYBE_LaunchTabApp LaunchTabApp
471 #endif
472
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,MAYBE_LaunchTabApp)473 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, MAYBE_LaunchTabApp) {
474 // Load an extension that calls launchApp() on any app that gets
475 // installed.
476 ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
477 ASSERT_TRUE(LoadExtension(
478 test_data_dir_.AppendASCII("management/launch_on_install")));
479 ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
480
481 // Code below assumes that the test starts with a single browser window
482 // hosting one tab.
483 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
484 ASSERT_EQ(1, browser()->tab_strip_model()->count());
485
486 // Load an app with app.launch.container = "tab".
487 std::string app_id;
488 LoadAndWaitForLaunch("management/launch_app_tab", &app_id);
489 ASSERT_FALSE(HasFatalFailure());
490
491 // Check that the app opened in a new tab of the existing browser.
492 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
493 ASSERT_EQ(2, browser()->tab_strip_model()->count());
494
495 extensions::ExtensionRegistry* registry =
496 extensions::ExtensionRegistry::Get(browser()->profile());
497 // Unload the extension.
498 UninstallExtension(app_id);
499 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
500 ASSERT_FALSE(registry->GetExtensionById(
501 app_id, extensions::ExtensionRegistry::EVERYTHING));
502
503 // Set a pref indicating that the user wants to launch in a window.
504 extensions::SetLaunchType(browser()->profile(), app_id,
505 extensions::LAUNCH_TYPE_WINDOW);
506
507 std::string app_id_new;
508 LoadAndWaitForLaunch("management/launch_app_tab", &app_id_new);
509 ASSERT_FALSE(HasFatalFailure());
510
511 // If the ID changed, then the pref will not apply to the app.
512 ASSERT_EQ(app_id, app_id_new);
513
514 // Find the app's browser. Opening in a new window will create
515 // a new browser.
516 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
517 Browser* app_browser = FindOtherBrowser(browser());
518 ASSERT_TRUE(app_browser->is_type_app());
519 }
520
521 // Flaky on MacOS: crbug.com/915339
522 #if defined(OS_MACOSX)
523 #define MAYBE_LaunchType DISABLED_LaunchType
524 #else
525 #define MAYBE_LaunchType LaunchType
526 #endif
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,MAYBE_LaunchType)527 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, MAYBE_LaunchType) {
528 LoadExtensions();
529 base::FilePath basedir = test_data_dir_.AppendASCII("management");
530 LoadNamedExtension(basedir, "packaged_app");
531
532 ASSERT_TRUE(RunExtensionSubtest("management/test", "launchType.html"));
533 }
534