1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/extensions/launch_util.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/values.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/extension_sync_service.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/extensions/extension_util.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/ui/host_desktop.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/pref_names.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "extensions/common/extension.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(USE_ASH) 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ash/shell.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace extensions { 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A preference set by the the NTP to persist the desired launch container type 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// used for apps. 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kPrefLaunchType[] = "launchType"; 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace launch_util { 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry->RegisterIntegerPref( 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_names::kBookmarkAppCreationLaunchType, 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LAUNCH_TYPE_WINDOW, 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace launch_util 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)LaunchType GetLaunchType(const ExtensionPrefs* prefs, 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const Extension* extension) { 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LaunchType result = LAUNCH_TYPE_DEFAULT; 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Launch hosted apps as windows by default for streamlined hosted apps. 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (util::IsStreamlinedHostedAppsEnabled() && 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension->id() != extension_misc::kChromeAppId) { 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result = LAUNCH_TYPE_WINDOW; 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int value = GetLaunchTypePrefValue(prefs, extension->id()); 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (value >= LAUNCH_TYPE_FIRST && value < NUM_LAUNCH_TYPES) 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result = static_cast<LaunchType>(value); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_MACOSX) 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // App windows are not yet supported on mac. Pref sync could make 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // the launch type LAUNCH_TYPE_WINDOW, even if there is no UI to set it 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // on mac. 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!extension->is_platform_app() && result == LAUNCH_TYPE_WINDOW) 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result = LAUNCH_TYPE_REGULAR; 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return result; 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)LaunchType GetLaunchTypePrefValue(const ExtensionPrefs* prefs, 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extension_id) { 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int value = LAUNCH_TYPE_INVALID; 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return prefs->ReadPrefAsInteger(extension_id, kPrefLaunchType, &value) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ? static_cast<LaunchType>(value) : LAUNCH_TYPE_INVALID; 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SetLaunchType(ExtensionService* service, 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extension_id, 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LaunchType launch_type) { 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(launch_type >= LAUNCH_TYPE_FIRST && launch_type < NUM_LAUNCH_TYPES); 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ExtensionPrefs::Get(service->profile())->UpdateExtensionPref( 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extension_id, 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kPrefLaunchType, 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new base::FundamentalValue(static_cast<int>(launch_type))); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Sync the launch type. 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Extension* extension = service->GetInstalledExtension(extension_id); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extension) { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionSyncService::Get(service->profile())-> 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncExtensionChangeIfNeeded(*extension); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)LaunchContainer GetLaunchContainer(const ExtensionPrefs* prefs, 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const Extension* extension) { 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LaunchContainer manifest_launch_container = 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AppLaunchInfo::GetLaunchContainer(extension); 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const LaunchContainer kInvalidLaunchContainer = 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static_cast<LaunchContainer>(-1); 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LaunchContainer result = kInvalidLaunchContainer; 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (manifest_launch_container == LAUNCH_CONTAINER_PANEL) { 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Apps with app.launch.container = 'panel' should always respect the 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // manifest setting. 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result = manifest_launch_container; 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (manifest_launch_container == LAUNCH_CONTAINER_TAB) { 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Look for prefs that indicate the user's choice of launch container. The 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // app's menu on the NTP provides a UI to set this preference. 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LaunchType prefs_launch_type = GetLaunchType(prefs, extension); 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (prefs_launch_type == LAUNCH_TYPE_WINDOW) { 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If the pref is set to launch a window (or no pref is set, and 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // window opening is the default), make the container a window. 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result = LAUNCH_CONTAINER_WINDOW; 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(USE_ASH) 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (prefs_launch_type == LAUNCH_TYPE_FULLSCREEN && 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH) { 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // LAUNCH_TYPE_FULLSCREEN launches in a maximized app window in ash. 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // For desktop chrome AURA on all platforms we should open the 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // application in full screen mode in the current tab, on the same 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // lines as non AURA chrome. 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result = LAUNCH_CONTAINER_WINDOW; 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // All other launch types (tab, pinned, fullscreen) are 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // implemented as tabs in a window. 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result = LAUNCH_CONTAINER_TAB; 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If a new value for app.launch.container is added, logic for it should be 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // added here. LAUNCH_CONTAINER_WINDOW is not present because there is no 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // way to set it in a manifest. 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED() << manifest_launch_container; 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // All paths should set |result|. 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (result == kInvalidLaunchContainer) { 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DLOG(FATAL) << "Failed to set a launch container."; 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result = LAUNCH_CONTAINER_TAB; 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return result; 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool HasPreferredLaunchContainer(const ExtensionPrefs* prefs, 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const Extension* extension) { 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int value = -1; 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LaunchContainer manifest_launch_container = 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AppLaunchInfo::GetLaunchContainer(extension); 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return manifest_launch_container == LAUNCH_CONTAINER_TAB && 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) prefs->ReadPrefAsInteger(extension->id(), kPrefLaunchType, &value); 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace extensions 158