Home | History | Annotate | Download | only in win
      1 // Copyright (c) 2012 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 "ui/base/win/shell.h"
      6 
      7 #include <dwmapi.h>
      8 #include <shlobj.h>  // Must be before propkey.
      9 #include <propkey.h>
     10 #include <shellapi.h>
     11 
     12 #include "base/command_line.h"
     13 #include "base/files/file_path.h"
     14 #include "base/native_library.h"
     15 #include "base/strings/string_util.h"
     16 #include "base/win/metro.h"
     17 #include "base/win/scoped_comptr.h"
     18 #include "base/win/win_util.h"
     19 #include "base/win/windows_version.h"
     20 #include "ui/base/ui_base_switches.h"
     21 
     22 namespace ui {
     23 namespace win {
     24 
     25 namespace {
     26 
     27 void SetAppDetailsForWindow(const string16& app_id,
     28                             const string16& app_icon,
     29                             const string16& relaunch_command,
     30                             const string16& relaunch_display_name,
     31                             HWND hwnd) {
     32   // This functionality is only available on Win7+. It also doesn't make sense
     33   // to do this for Chrome Metro.
     34   if (base::win::GetVersion() < base::win::VERSION_WIN7 ||
     35       base::win::IsMetroProcess())
     36     return;
     37   base::win::ScopedComPtr<IPropertyStore> pps;
     38   HRESULT result = SHGetPropertyStoreForWindow(
     39       hwnd, __uuidof(*pps), reinterpret_cast<void**>(pps.Receive()));
     40   if (S_OK == result) {
     41     if (!app_id.empty())
     42       base::win::SetAppIdForPropertyStore(pps, app_id.c_str());
     43     if (!app_icon.empty()) {
     44       base::win::SetStringValueForPropertyStore(
     45           pps, PKEY_AppUserModel_RelaunchIconResource, app_icon.c_str());
     46     }
     47     if (!relaunch_command.empty()) {
     48       base::win::SetStringValueForPropertyStore(
     49           pps, PKEY_AppUserModel_RelaunchCommand, relaunch_command.c_str());
     50     }
     51     if (!relaunch_display_name.empty()) {
     52       base::win::SetStringValueForPropertyStore(
     53           pps, PKEY_AppUserModel_RelaunchDisplayNameResource,
     54           relaunch_display_name.c_str());
     55     }
     56   }
     57 }
     58 
     59 }  // namespace
     60 
     61 // Show the Windows "Open With" dialog box to ask the user to pick an app to
     62 // open the file with.
     63 bool OpenItemWithExternalApp(const string16& full_path) {
     64   SHELLEXECUTEINFO sei = { sizeof(sei) };
     65   sei.fMask = SEE_MASK_FLAG_DDEWAIT;
     66   sei.nShow = SW_SHOWNORMAL;
     67   sei.lpVerb = L"openas";
     68   sei.lpFile = full_path.c_str();
     69   return (TRUE == ::ShellExecuteExW(&sei));
     70 }
     71 
     72 bool OpenAnyViaShell(const string16& full_path,
     73                      const string16& directory,
     74                      const string16& args,
     75                      DWORD mask) {
     76   SHELLEXECUTEINFO sei = { sizeof(sei) };
     77   sei.fMask = mask;
     78   sei.nShow = SW_SHOWNORMAL;
     79   sei.lpFile = full_path.c_str();
     80   sei.lpDirectory = directory.c_str();
     81   if (!args.empty())
     82     sei.lpParameters = args.c_str();
     83 
     84   if (::ShellExecuteExW(&sei))
     85     return true;
     86   if (::GetLastError() == ERROR_NO_ASSOCIATION)
     87     return OpenItemWithExternalApp(full_path);
     88   return false;
     89 }
     90 
     91 bool OpenItemViaShell(const base::FilePath& full_path) {
     92   return OpenAnyViaShell(full_path.value(), full_path.DirName().value(),
     93                          string16(), 0);
     94 }
     95 
     96 bool OpenItemViaShellNoZoneCheck(const base::FilePath& full_path) {
     97   return OpenAnyViaShell(full_path.value(), string16(), string16(),
     98                          SEE_MASK_NOZONECHECKS | SEE_MASK_FLAG_DDEWAIT);
     99 }
    100 
    101 void SetAppIdForWindow(const string16& app_id, HWND hwnd) {
    102   SetAppDetailsForWindow(app_id, string16(), string16(), string16(), hwnd);
    103 }
    104 
    105 void SetAppIconForWindow(const string16& app_icon, HWND hwnd) {
    106   SetAppDetailsForWindow(string16(), app_icon, string16(), string16(), hwnd);
    107 }
    108 
    109 void SetRelaunchDetailsForWindow(const string16& relaunch_command,
    110                                  const string16& display_name,
    111                                  HWND hwnd) {
    112   SetAppDetailsForWindow(string16(),
    113                          string16(),
    114                          relaunch_command,
    115                          display_name,
    116                          hwnd);
    117 }
    118 
    119 bool IsAeroGlassEnabled() {
    120   // For testing in Win8 (where it is not possible to disable composition) the
    121   // user can specify this command line switch to mimic the behavior.  In this
    122   // mode, cross-HWND transparency is not supported and various types of
    123   // widgets fallback to more simplified rendering behavior.
    124   if (CommandLine::ForCurrentProcess()->HasSwitch(
    125       switches::kDisableDwmComposition))
    126     return false;
    127 
    128   if (base::win::GetVersion() < base::win::VERSION_VISTA)
    129     return false;
    130   // If composition is not enabled, we behave like on XP.
    131   BOOL enabled = FALSE;
    132   return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
    133 }
    134 
    135 }  // namespace win
    136 }  // namespace ui
    137