Home | History | Annotate | Download | only in extensions
      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