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