Avi Drissman | 4a8573c | 2022-09-09 19:35:54 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 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 "chrome/browser/extensions/launch_util.h" |
| 6 | |
Jinho Bang | b5216cec | 2018-01-17 19:43:11 | [diff] [blame] | 7 | #include <memory> |
| 8 | |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 9 | #include "base/values.h" |
avi | a2f4804a | 2015-12-24 23:11:13 | [diff] [blame] | 10 | #include "build/build_config.h" |
Yuta Hijikata | 1290fee2 | 2020-11-25 09:46:28 | [diff] [blame] | 11 | #include "build/chromeos_buildflags.h" |
Glen Robertson | 80d9274 | 2024-05-17 05:33:41 | [diff] [blame] | 12 | #include "chrome/browser/extensions/bookmark_app_util.h" |
[email protected] | dccba4f8 | 2014-05-29 00:52:56 | [diff] [blame] | 13 | #include "chrome/browser/extensions/extension_sync_service.h" |
[email protected] | 15aadda | 2013-12-13 15:10:09 | [diff] [blame] | 14 | #include "chrome/common/extensions/extension_constants.h" |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 15 | #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
[email protected] | f0c8c499 | 2014-05-15 17:37:26 | [diff] [blame] | 16 | #include "components/pref_registry/pref_registry_syncable.h" |
[email protected] | 489db084 | 2014-01-22 18:20:03 | [diff] [blame] | 17 | #include "extensions/browser/extension_prefs.h" |
macourteau | 86b29d8 | 2015-01-23 13:24:45 | [diff] [blame] | 18 | #include "extensions/browser/extension_registry.h" |
[email protected] | 05d3647e | 2014-02-11 04:59:09 | [diff] [blame] | 19 | #include "extensions/browser/pref_names.h" |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 20 | #include "extensions/common/extension.h" |
| 21 | |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 22 | namespace extensions { |
| 23 | namespace { |
| 24 | |
| 25 | // A preference set by the the NTP to persist the desired launch container type |
| 26 | // used for apps. |
| 27 | const char kPrefLaunchType[] = "launchType"; |
| 28 | |
| 29 | } // namespace |
| 30 | |
| 31 | LaunchType GetLaunchType(const ExtensionPrefs* prefs, |
| 32 | const Extension* extension) { |
Solomon Kinard | f5eca78 | 2023-03-29 19:52:03 | [diff] [blame] | 33 | if (!extension) { |
Hidehiko Abe | 8c6343b | 2022-02-14 04:15:03 | [diff] [blame] | 34 | return LAUNCH_TYPE_INVALID; |
Solomon Kinard | f5eca78 | 2023-03-29 19:52:03 | [diff] [blame] | 35 | } |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 36 | LaunchType result = LAUNCH_TYPE_DEFAULT; |
| 37 | |
[email protected] | a9f74a6 | 2014-01-10 06:48:36 | [diff] [blame] | 38 | int value = GetLaunchTypePrefValue(prefs, extension->id()); |
| 39 | if (value >= LAUNCH_TYPE_FIRST && value < NUM_LAUNCH_TYPES) |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 40 | result = static_cast<LaunchType>(value); |
[email protected] | a9f74a6 | 2014-01-10 06:48:36 | [diff] [blame] | 41 | |
Ben Wells | 6dcbe65 | 2018-08-24 12:59:09 | [diff] [blame] | 42 | // Force hosted apps that are not locally installed to open in tabs. |
| 43 | if (extension->is_hosted_app() && |
| 44 | !BookmarkAppIsLocallyInstalled(prefs, extension)) { |
| 45 | result = LAUNCH_TYPE_REGULAR; |
Christopher Cameron | e138574 | 2019-04-05 20:37:25 | [diff] [blame] | 46 | } else if (result == LAUNCH_TYPE_PINNED) { |
jackhou | 8b77ff0fc | 2015-02-17 00:53:55 | [diff] [blame] | 47 | result = LAUNCH_TYPE_REGULAR; |
Christopher Cameron | e138574 | 2019-04-05 20:37:25 | [diff] [blame] | 48 | } else if (result == LAUNCH_TYPE_FULLSCREEN) { |
| 49 | result = LAUNCH_TYPE_WINDOW; |
dominickn | 2b10cbd | 2015-08-20 02:09:18 | [diff] [blame] | 50 | } |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 51 | return result; |
| 52 | } |
| 53 | |
[email protected] | a9f74a6 | 2014-01-10 06:48:36 | [diff] [blame] | 54 | LaunchType GetLaunchTypePrefValue(const ExtensionPrefs* prefs, |
| 55 | const std::string& extension_id) { |
| 56 | int value = LAUNCH_TYPE_INVALID; |
| 57 | return prefs->ReadPrefAsInteger(extension_id, kPrefLaunchType, &value) |
| 58 | ? static_cast<LaunchType>(value) : LAUNCH_TYPE_INVALID; |
| 59 | } |
| 60 | |
macourteau | 86b29d8 | 2015-01-23 13:24:45 | [diff] [blame] | 61 | void SetLaunchType(content::BrowserContext* context, |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 62 | const std::string& extension_id, |
| 63 | LaunchType launch_type) { |
[email protected] | a9f74a6 | 2014-01-10 06:48:36 | [diff] [blame] | 64 | DCHECK(launch_type >= LAUNCH_TYPE_FIRST && launch_type < NUM_LAUNCH_TYPES); |
| 65 | |
macourteau | 86b29d8 | 2015-01-23 13:24:45 | [diff] [blame] | 66 | ExtensionPrefs::Get(context)->UpdateExtensionPref( |
| 67 | extension_id, kPrefLaunchType, |
David Bertoni | 517c487b | 2023-02-25 05:58:31 | [diff] [blame] | 68 | base::Value(static_cast<int>(launch_type))); |
[email protected] | a9f74a6 | 2014-01-10 06:48:36 | [diff] [blame] | 69 | |
| 70 | // Sync the launch type. |
macourteau | 86b29d8 | 2015-01-23 13:24:45 | [diff] [blame] | 71 | const Extension* extension = |
| 72 | ExtensionRegistry::Get(context) |
| 73 | ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); |
| 74 | if (extension) |
| 75 | ExtensionSyncService::Get(context)->SyncExtensionChangeIfNeeded(*extension); |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 76 | } |
| 77 | |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 78 | apps::LaunchContainer GetLaunchContainer(const ExtensionPrefs* prefs, |
| 79 | const Extension* extension) { |
| 80 | apps::LaunchContainer manifest_launch_container = |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 81 | AppLaunchInfo::GetLaunchContainer(extension); |
| 82 | |
Arthur Sonzogni | fe132ee | 2024-01-15 11:01:04 | [diff] [blame] | 83 | std::optional<apps::LaunchContainer> result; |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 84 | |
Eric Willigers | 618e130 | 2019-06-23 23:03:47 | [diff] [blame] | 85 | if (manifest_launch_container == |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 86 | apps::LaunchContainer::kLaunchContainerPanelDeprecated) { |
Hiroshige Hayashizaki | a4756d2 | 2020-04-01 06:48:55 | [diff] [blame] | 87 | result = manifest_launch_container; |
| 88 | } else if (manifest_launch_container == |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 89 | apps::LaunchContainer::kLaunchContainerTab) { |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 90 | // Look for prefs that indicate the user's choice of launch container. The |
| 91 | // app's menu on the NTP provides a UI to set this preference. |
| 92 | LaunchType prefs_launch_type = GetLaunchType(prefs, extension); |
| 93 | |
| 94 | if (prefs_launch_type == LAUNCH_TYPE_WINDOW) { |
| 95 | // If the pref is set to launch a window (or no pref is set, and |
| 96 | // window opening is the default), make the container a window. |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 97 | result = apps::LaunchContainer::kLaunchContainerWindow; |
David Bertoni | 53445f6 | 2024-10-11 19:50:54 | [diff] [blame^] | 98 | #if BUILDFLAG(IS_CHROMEOS) |
scottmg | d12621f | 2016-03-18 16:14:27 | [diff] [blame] | 99 | } else if (prefs_launch_type == LAUNCH_TYPE_FULLSCREEN) { |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 100 | // LAUNCH_TYPE_FULLSCREEN launches in a maximized app window in ash. |
| 101 | // For desktop chrome AURA on all platforms we should open the |
| 102 | // application in full screen mode in the current tab, on the same |
| 103 | // lines as non AURA chrome. |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 104 | result = apps::LaunchContainer::kLaunchContainerWindow; |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 105 | #endif |
| 106 | } else { |
| 107 | // All other launch types (tab, pinned, fullscreen) are |
| 108 | // implemented as tabs in a window. |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 109 | result = apps::LaunchContainer::kLaunchContainerTab; |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 110 | } |
| 111 | } else { |
| 112 | // If a new value for app.launch.container is added, logic for it should be |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 113 | // added here. apps::LaunchContainer::kLaunchContainerWindow is not |
Devlin Cronin | ed380dc4 | 2022-01-17 01:23:47 | [diff] [blame] | 114 | // present because there is no way to set it in a manifest. |
Peter Boström | 0b2c27d | 2024-05-14 20:42:56 | [diff] [blame] | 115 | NOTREACHED_IN_MIGRATION() << static_cast<int>(manifest_launch_container); |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | // All paths should set |result|. |
Hans Wennborg | d3f6afb | 2017-12-09 00:16:37 | [diff] [blame] | 119 | if (!result) { |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 120 | DLOG(FATAL) << "Failed to set a launch container."; |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 121 | result = apps::LaunchContainer::kLaunchContainerTab; |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 122 | } |
| 123 | |
Hans Wennborg | d3f6afb | 2017-12-09 00:16:37 | [diff] [blame] | 124 | return *result; |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | bool HasPreferredLaunchContainer(const ExtensionPrefs* prefs, |
| 128 | const Extension* extension) { |
| 129 | int value = -1; |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 130 | apps::LaunchContainer manifest_launch_container = |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 131 | AppLaunchInfo::GetLaunchContainer(extension); |
Devlin Cronin | ed380dc4 | 2022-01-17 01:23:47 | [diff] [blame] | 132 | return manifest_launch_container == |
Nancy Wang | dcfd56a0 | 2022-07-04 17:16:00 | [diff] [blame] | 133 | apps::LaunchContainer::kLaunchContainerTab && |
Eric Willigers | 618e130 | 2019-06-23 23:03:47 | [diff] [blame] | 134 | prefs->ReadPrefAsInteger(extension->id(), kPrefLaunchType, &value); |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 135 | } |
| 136 | |
benwells | 0a78dba | 2015-05-06 23:11:08 | [diff] [blame] | 137 | bool LaunchesInWindow(content::BrowserContext* context, |
| 138 | const Extension* extension) { |
| 139 | return GetLaunchType(ExtensionPrefs::Get(context), extension) == |
| 140 | LAUNCH_TYPE_WINDOW; |
| 141 | } |
| 142 | |
[email protected] | 31e4d8f | 2013-12-05 11:32:54 | [diff] [blame] | 143 | } // namespace extensions |