1 // Copyright (c) 2013 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 "chrome/browser/extensions/launch_util.h"
6
7 #include <memory>
8
9 #include "base/values.h"
10 #include "build/build_config.h"
11 #include "chrome/browser/extensions/extension_sync_service.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
14 #include "chrome/common/extensions/extension_constants.h"
15 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
16 #include "components/pref_registry/pref_registry_syncable.h"
17 #include "extensions/browser/extension_prefs.h"
18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/browser/pref_names.h"
20 #include "extensions/common/extension.h"
21
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
GetLaunchType(const ExtensionPrefs * prefs,const Extension * extension)31 LaunchType GetLaunchType(const ExtensionPrefs* prefs,
32 const Extension* extension) {
33 LaunchType result = LAUNCH_TYPE_DEFAULT;
34
35 int value = GetLaunchTypePrefValue(prefs, extension->id());
36 if (value >= LAUNCH_TYPE_FIRST && value < NUM_LAUNCH_TYPES)
37 result = static_cast<LaunchType>(value);
38
39 // Force hosted apps that are not locally installed to open in tabs.
40 if (extension->is_hosted_app() &&
41 !BookmarkAppIsLocallyInstalled(prefs, extension)) {
42 result = LAUNCH_TYPE_REGULAR;
43 } else if (result == LAUNCH_TYPE_PINNED) {
44 result = LAUNCH_TYPE_REGULAR;
45 } else if (result == LAUNCH_TYPE_FULLSCREEN) {
46 result = LAUNCH_TYPE_WINDOW;
47 }
48 return result;
49 }
50
GetLaunchTypePrefValue(const ExtensionPrefs * prefs,const std::string & extension_id)51 LaunchType GetLaunchTypePrefValue(const ExtensionPrefs* prefs,
52 const std::string& extension_id) {
53 int value = LAUNCH_TYPE_INVALID;
54 return prefs->ReadPrefAsInteger(extension_id, kPrefLaunchType, &value)
55 ? static_cast<LaunchType>(value) : LAUNCH_TYPE_INVALID;
56 }
57
SetLaunchType(content::BrowserContext * context,const std::string & extension_id,LaunchType launch_type)58 void SetLaunchType(content::BrowserContext* context,
59 const std::string& extension_id,
60 LaunchType launch_type) {
61 DCHECK(launch_type >= LAUNCH_TYPE_FIRST && launch_type < NUM_LAUNCH_TYPES);
62
63 ExtensionPrefs::Get(context)->UpdateExtensionPref(
64 extension_id, kPrefLaunchType,
65 std::make_unique<base::Value>(static_cast<int>(launch_type)));
66
67 // Sync the launch type.
68 const Extension* extension =
69 ExtensionRegistry::Get(context)
70 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
71 if (extension)
72 ExtensionSyncService::Get(context)->SyncExtensionChangeIfNeeded(*extension);
73 }
74
GetLaunchContainer(const ExtensionPrefs * prefs,const Extension * extension)75 LaunchContainer GetLaunchContainer(const ExtensionPrefs* prefs,
76 const Extension* extension) {
77 LaunchContainer manifest_launch_container =
78 AppLaunchInfo::GetLaunchContainer(extension);
79
80 base::Optional<LaunchContainer> result;
81
82 if (manifest_launch_container ==
83 LaunchContainer::kLaunchContainerPanelDeprecated) {
84 result = manifest_launch_container;
85 } else if (manifest_launch_container ==
86 LaunchContainer::kLaunchContainerTab) {
87 // Look for prefs that indicate the user's choice of launch container. The
88 // app's menu on the NTP provides a UI to set this preference.
89 LaunchType prefs_launch_type = GetLaunchType(prefs, extension);
90
91 if (prefs_launch_type == LAUNCH_TYPE_WINDOW) {
92 // If the pref is set to launch a window (or no pref is set, and
93 // window opening is the default), make the container a window.
94 result = LaunchContainer::kLaunchContainerWindow;
95 #if defined(OS_CHROMEOS)
96 } else if (prefs_launch_type == LAUNCH_TYPE_FULLSCREEN) {
97 // LAUNCH_TYPE_FULLSCREEN launches in a maximized app window in ash.
98 // For desktop chrome AURA on all platforms we should open the
99 // application in full screen mode in the current tab, on the same
100 // lines as non AURA chrome.
101 result = LaunchContainer::kLaunchContainerWindow;
102 #endif
103 } else {
104 // All other launch types (tab, pinned, fullscreen) are
105 // implemented as tabs in a window.
106 result = LaunchContainer::kLaunchContainerTab;
107 }
108 } else {
109 // If a new value for app.launch.container is added, logic for it should be
110 // added here. LaunchContainer::kLaunchContainerWindow is not present
111 // because there is no way to set it in a manifest.
112 NOTREACHED() << manifest_launch_container;
113 }
114
115 // All paths should set |result|.
116 if (!result) {
117 DLOG(FATAL) << "Failed to set a launch container.";
118 result = LaunchContainer::kLaunchContainerTab;
119 }
120
121 return *result;
122 }
123
HasPreferredLaunchContainer(const ExtensionPrefs * prefs,const Extension * extension)124 bool HasPreferredLaunchContainer(const ExtensionPrefs* prefs,
125 const Extension* extension) {
126 int value = -1;
127 LaunchContainer manifest_launch_container =
128 AppLaunchInfo::GetLaunchContainer(extension);
129 return manifest_launch_container == LaunchContainer::kLaunchContainerTab &&
130 prefs->ReadPrefAsInteger(extension->id(), kPrefLaunchType, &value);
131 }
132
LaunchesInWindow(content::BrowserContext * context,const Extension * extension)133 bool LaunchesInWindow(content::BrowserContext* context,
134 const Extension* extension) {
135 return GetLaunchType(ExtensionPrefs::Get(context), extension) ==
136 LAUNCH_TYPE_WINDOW;
137 }
138
139 } // namespace extensions
140