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