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