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 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 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 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 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 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 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