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.
5 #include "chrome/browser/extensions/launch_util.h"
7 #include "base/command_line.h"
8 #include "base/values.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/ui/host_desktop.h"
11 #include "chrome/common/chrome_switches.h"
12 #include "chrome/common/extensions/extension_constants.h"
13 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
14 #include "components/user_prefs/pref_registry_syncable.h"
15 #include "extensions/browser/extension_prefs.h"
16 #include "extensions/browser/pref_names.h"
17 #include "extensions/common/extension.h"
20 #include "win8/util/win8_util.h"
24 #include "ash/shell.h"
27 namespace extensions
{
30 // A preference set by the the NTP to persist the desired launch container type
32 const char kPrefLaunchType
[] = "launchType";
36 namespace launch_util
{
39 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable
* registry
) {
40 registry
->RegisterIntegerPref(
41 pref_names::kBookmarkAppCreationLaunchType
,
43 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
46 } // namespace launch_util
48 LaunchType
GetLaunchType(const ExtensionPrefs
* prefs
,
49 const Extension
* extension
) {
50 LaunchType result
= LAUNCH_TYPE_DEFAULT
;
52 // Launch hosted apps as windows by default for streamlined hosted apps.
53 if (CommandLine::ForCurrentProcess()->
54 HasSwitch(switches::kEnableStreamlinedHostedApps
) &&
55 extension
->id() != extension_misc::kChromeAppId
) {
56 result
= LAUNCH_TYPE_WINDOW
;
59 int value
= GetLaunchTypePrefValue(prefs
, extension
->id());
60 if (value
>= LAUNCH_TYPE_FIRST
&& value
< NUM_LAUNCH_TYPES
)
61 result
= static_cast<LaunchType
>(value
);
63 #if defined(OS_MACOSX)
64 // App windows are not yet supported on mac. Pref sync could make
65 // the launch type LAUNCH_TYPE_WINDOW, even if there is no UI to set it
67 if (!extension
->is_platform_app() && result
== LAUNCH_TYPE_WINDOW
)
68 result
= LAUNCH_TYPE_REGULAR
;
72 // We don't support app windows in Windows 8 single window Metro mode.
73 if (win8::IsSingleWindowMetroMode() && result
== LAUNCH_TYPE_WINDOW
)
74 result
= LAUNCH_TYPE_REGULAR
;
80 LaunchType
GetLaunchTypePrefValue(const ExtensionPrefs
* prefs
,
81 const std::string
& extension_id
) {
82 int value
= LAUNCH_TYPE_INVALID
;
83 return prefs
->ReadPrefAsInteger(extension_id
, kPrefLaunchType
, &value
)
84 ? static_cast<LaunchType
>(value
) : LAUNCH_TYPE_INVALID
;
87 void SetLaunchType(ExtensionService
* service
,
88 const std::string
& extension_id
,
89 LaunchType launch_type
) {
90 DCHECK(launch_type
>= LAUNCH_TYPE_FIRST
&& launch_type
< NUM_LAUNCH_TYPES
);
92 service
->extension_prefs()->UpdateExtensionPref(extension_id
, kPrefLaunchType
,
93 new base::FundamentalValue(static_cast<int>(launch_type
)));
95 // Sync the launch type.
96 const Extension
* extension
= service
->GetInstalledExtension(extension_id
);
98 ExtensionSyncService::Get(service
->profile())->
99 SyncExtensionChangeIfNeeded(*extension
);
103 LaunchContainer
GetLaunchContainer(const ExtensionPrefs
* prefs
,
104 const Extension
* extension
) {
105 LaunchContainer manifest_launch_container
=
106 AppLaunchInfo::GetLaunchContainer(extension
);
108 const LaunchContainer kInvalidLaunchContainer
=
109 static_cast<LaunchContainer
>(-1);
111 LaunchContainer result
= kInvalidLaunchContainer
;
113 if (manifest_launch_container
== LAUNCH_CONTAINER_PANEL
) {
114 // Apps with app.launch.container = 'panel' should always respect the
116 result
= manifest_launch_container
;
117 } else if (manifest_launch_container
== LAUNCH_CONTAINER_TAB
) {
118 // Look for prefs that indicate the user's choice of launch container. The
119 // app's menu on the NTP provides a UI to set this preference.
120 LaunchType prefs_launch_type
= GetLaunchType(prefs
, extension
);
122 if (prefs_launch_type
== LAUNCH_TYPE_WINDOW
) {
123 // If the pref is set to launch a window (or no pref is set, and
124 // window opening is the default), make the container a window.
125 result
= LAUNCH_CONTAINER_WINDOW
;
127 } else if (prefs_launch_type
== LAUNCH_TYPE_FULLSCREEN
&&
128 chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH
) {
129 // LAUNCH_TYPE_FULLSCREEN launches in a maximized app window in ash.
130 // For desktop chrome AURA on all platforms we should open the
131 // application in full screen mode in the current tab, on the same
132 // lines as non AURA chrome.
133 result
= LAUNCH_CONTAINER_WINDOW
;
136 // All other launch types (tab, pinned, fullscreen) are
137 // implemented as tabs in a window.
138 result
= LAUNCH_CONTAINER_TAB
;
141 // If a new value for app.launch.container is added, logic for it should be
142 // added here. LAUNCH_CONTAINER_WINDOW is not present because there is no
143 // way to set it in a manifest.
144 NOTREACHED() << manifest_launch_container
;
147 // All paths should set |result|.
148 if (result
== kInvalidLaunchContainer
) {
149 DLOG(FATAL
) << "Failed to set a launch container.";
150 result
= LAUNCH_CONTAINER_TAB
;
156 bool HasPreferredLaunchContainer(const ExtensionPrefs
* prefs
,
157 const Extension
* extension
) {
159 LaunchContainer manifest_launch_container
=
160 AppLaunchInfo::GetLaunchContainer(extension
);
161 return manifest_launch_container
== LAUNCH_CONTAINER_TAB
&&
162 prefs
->ReadPrefAsInteger(extension
->id(), kPrefLaunchType
, &value
);
165 } // namespace extensions