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 "base/values.h"
8 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/extensions/extension_sync_service.h"
10 #include "chrome/browser/extensions/extension_util.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/host_desktop.h"
13 #include "chrome/common/extensions/extension_constants.h"
14 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
15 #include "components/pref_registry/pref_registry_syncable.h"
16 #include "extensions/browser/extension_prefs.h"
17 #include "extensions/browser/pref_names.h"
18 #include "extensions/common/extension.h"
19
20 #if defined(USE_ASH)
21 #include "ash/shell.h"
22 #endif
23
24 namespace extensions {
25 namespace {
26
27 // A preference set by the the NTP to persist the desired launch container type
28 // used for apps.
29 const char kPrefLaunchType[] = "launchType";
30
31 } // namespace
32
33 namespace launch_util {
34
35 // static
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)36 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
37 registry->RegisterIntegerPref(
38 pref_names::kBookmarkAppCreationLaunchType,
39 LAUNCH_TYPE_WINDOW,
40 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
41 }
42
43 } // namespace launch_util
44
GetLaunchType(const ExtensionPrefs * prefs,const Extension * extension)45 LaunchType GetLaunchType(const ExtensionPrefs* prefs,
46 const Extension* extension) {
47 LaunchType result = LAUNCH_TYPE_DEFAULT;
48
49 // Launch hosted apps as windows by default for streamlined hosted apps.
50 if (util::IsStreamlinedHostedAppsEnabled() &&
51 extension->id() != extension_misc::kChromeAppId) {
52 result = LAUNCH_TYPE_WINDOW;
53 }
54
55 int value = GetLaunchTypePrefValue(prefs, extension->id());
56 if (value >= LAUNCH_TYPE_FIRST && value < NUM_LAUNCH_TYPES)
57 result = static_cast<LaunchType>(value);
58
59 #if defined(OS_MACOSX)
60 // App windows are not yet supported on mac. Pref sync could make
61 // the launch type LAUNCH_TYPE_WINDOW, even if there is no UI to set it
62 // on mac.
63 if (!extension->is_platform_app() && result == LAUNCH_TYPE_WINDOW)
64 result = LAUNCH_TYPE_REGULAR;
65 #endif
66
67 return result;
68 }
69
GetLaunchTypePrefValue(const ExtensionPrefs * prefs,const std::string & extension_id)70 LaunchType GetLaunchTypePrefValue(const ExtensionPrefs* prefs,
71 const std::string& extension_id) {
72 int value = LAUNCH_TYPE_INVALID;
73 return prefs->ReadPrefAsInteger(extension_id, kPrefLaunchType, &value)
74 ? static_cast<LaunchType>(value) : LAUNCH_TYPE_INVALID;
75 }
76
SetLaunchType(ExtensionService * service,const std::string & extension_id,LaunchType launch_type)77 void SetLaunchType(ExtensionService* service,
78 const std::string& extension_id,
79 LaunchType launch_type) {
80 DCHECK(launch_type >= LAUNCH_TYPE_FIRST && launch_type < NUM_LAUNCH_TYPES);
81
82 ExtensionPrefs::Get(service->profile())->UpdateExtensionPref(
83 extension_id,
84 kPrefLaunchType,
85 new base::FundamentalValue(static_cast<int>(launch_type)));
86
87 // Sync the launch type.
88 const Extension* extension = service->GetInstalledExtension(extension_id);
89 if (extension) {
90 ExtensionSyncService::Get(service->profile())->
91 SyncExtensionChangeIfNeeded(*extension);
92 }
93 }
94
GetLaunchContainer(const ExtensionPrefs * prefs,const Extension * extension)95 LaunchContainer GetLaunchContainer(const ExtensionPrefs* prefs,
96 const Extension* extension) {
97 LaunchContainer manifest_launch_container =
98 AppLaunchInfo::GetLaunchContainer(extension);
99
100 const LaunchContainer kInvalidLaunchContainer =
101 static_cast<LaunchContainer>(-1);
102
103 LaunchContainer result = kInvalidLaunchContainer;
104
105 if (manifest_launch_container == LAUNCH_CONTAINER_PANEL) {
106 // Apps with app.launch.container = 'panel' should always respect the
107 // manifest setting.
108 result = manifest_launch_container;
109 } else if (manifest_launch_container == LAUNCH_CONTAINER_TAB) {
110 // Look for prefs that indicate the user's choice of launch container. The
111 // app's menu on the NTP provides a UI to set this preference.
112 LaunchType prefs_launch_type = GetLaunchType(prefs, extension);
113
114 if (prefs_launch_type == LAUNCH_TYPE_WINDOW) {
115 // If the pref is set to launch a window (or no pref is set, and
116 // window opening is the default), make the container a window.
117 result = LAUNCH_CONTAINER_WINDOW;
118 #if defined(USE_ASH)
119 } else if (prefs_launch_type == LAUNCH_TYPE_FULLSCREEN &&
120 chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH) {
121 // LAUNCH_TYPE_FULLSCREEN launches in a maximized app window in ash.
122 // For desktop chrome AURA on all platforms we should open the
123 // application in full screen mode in the current tab, on the same
124 // lines as non AURA chrome.
125 result = LAUNCH_CONTAINER_WINDOW;
126 #endif
127 } else {
128 // All other launch types (tab, pinned, fullscreen) are
129 // implemented as tabs in a window.
130 result = LAUNCH_CONTAINER_TAB;
131 }
132 } else {
133 // If a new value for app.launch.container is added, logic for it should be
134 // added here. LAUNCH_CONTAINER_WINDOW is not present because there is no
135 // way to set it in a manifest.
136 NOTREACHED() << manifest_launch_container;
137 }
138
139 // All paths should set |result|.
140 if (result == kInvalidLaunchContainer) {
141 DLOG(FATAL) << "Failed to set a launch container.";
142 result = LAUNCH_CONTAINER_TAB;
143 }
144
145 return result;
146 }
147
HasPreferredLaunchContainer(const ExtensionPrefs * prefs,const Extension * extension)148 bool HasPreferredLaunchContainer(const ExtensionPrefs* prefs,
149 const Extension* extension) {
150 int value = -1;
151 LaunchContainer manifest_launch_container =
152 AppLaunchInfo::GetLaunchContainer(extension);
153 return manifest_launch_container == LAUNCH_CONTAINER_TAB &&
154 prefs->ReadPrefAsInteger(extension->id(), kPrefLaunchType, &value);
155 }
156
157 } // namespace extensions
158