| Index: ui/base/win/shell.cc
|
| diff --git a/ui/base/win/shell.cc b/ui/base/win/shell.cc
|
| index 9e47f8c94ac45f50bdeb8e5d0760135c87816198..2a5bd29798da5b9ec878477e1007f07a87eb5c08 100644
|
| --- a/ui/base/win/shell.cc
|
| +++ b/ui/base/win/shell.cc
|
| @@ -11,9 +11,11 @@
|
|
|
| #include "base/command_line.h"
|
| #include "base/debug/alias.h"
|
| +#include "base/files/file.h"
|
| #include "base/files/file_path.h"
|
| #include "base/native_library.h"
|
| #include "base/strings/string_util.h"
|
| +#include "base/threading/thread_restrictions.h"
|
| #include "base/win/metro.h"
|
| #include "base/win/scoped_comptr.h"
|
| #include "base/win/win_util.h"
|
| @@ -25,15 +27,39 @@ namespace win {
|
|
|
| namespace {
|
|
|
| -// Show the Windows "Open With" dialog box to ask the user to pick an app to
|
| -// open the file with.
|
| -bool OpenItemWithExternalApp(const base::string16& full_path) {
|
| - SHELLEXECUTEINFO sei = { sizeof(sei) };
|
| - sei.fMask = SEE_MASK_FLAG_DDEWAIT;
|
| +// Default ShellExecuteEx flags used with the "openas" verb.
|
| +//
|
| +// SEE_MASK_NOASYNC is specified so that ShellExecuteEx can be invoked from a
|
| +// thread whose message loop may not wait around long enough for the
|
| +// asynchronous tasks initiated by ShellExecuteEx to complete. Using this flag
|
| +// causes ShellExecuteEx() to block until these tasks complete.
|
| +const DWORD kDefaultOpenAsFlags = SEE_MASK_NOASYNC;
|
| +
|
| +// Default ShellExecuteEx flags used with the "explore", "open" or default verb.
|
| +//
|
| +// See kDefaultOpenFlags for description SEE_MASK_NOASYNC flag.
|
| +// SEE_MASK_FLAG_NO_UI is used to suppress any error message boxes that might be
|
| +// displayed if there is an error in opening the file. Failure in invoking the
|
| +// "open" actions result in invocation of the "saveas" verb, making the error
|
| +// dialog superfluous.
|
| +const DWORD kDefaultOpenFlags = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI;
|
| +
|
| +// Invokes ShellExecuteExW() with the given parameters.
|
| +DWORD InvokeShellExecute(const base::string16 path,
|
| + const base::string16 working_directory,
|
| + const base::string16 args,
|
| + const base::string16 verb,
|
| + DWORD mask) {
|
| + base::ThreadRestrictions::AssertIOAllowed();
|
| + SHELLEXECUTEINFO sei = {sizeof(sei)};
|
| + sei.fMask = mask;
|
| sei.nShow = SW_SHOWNORMAL;
|
| - sei.lpVerb = L"openas";
|
| - sei.lpFile = full_path.c_str();
|
| - return (TRUE == ::ShellExecuteExW(&sei));
|
| + sei.lpVerb = (verb.empty() ? nullptr : verb.c_str());
|
| + sei.lpFile = path.c_str();
|
| + sei.lpDirectory =
|
| + (working_directory.empty() ? nullptr : working_directory.c_str());
|
| + sei.lpParameters = (args.empty() ? nullptr : args.c_str());
|
| + return ::ShellExecuteExW(&sei) ? ERROR_SUCCESS : ::GetLastError();
|
| }
|
|
|
| } // namespace
|
| @@ -42,24 +68,32 @@ bool OpenAnyViaShell(const base::string16& full_path,
|
| const base::string16& directory,
|
| const base::string16& args,
|
| DWORD mask) {
|
| - SHELLEXECUTEINFO sei = { sizeof(sei) };
|
| - sei.fMask = mask;
|
| - sei.nShow = SW_SHOWNORMAL;
|
| - sei.lpFile = full_path.c_str();
|
| - sei.lpDirectory = directory.c_str();
|
| - if (!args.empty())
|
| - sei.lpParameters = args.c_str();
|
| -
|
| - if (::ShellExecuteExW(&sei))
|
| + DWORD open_result =
|
| + InvokeShellExecute(full_path, directory, args, base::string16(), mask);
|
| + if (open_result == ERROR_SUCCESS)
|
| return true;
|
| - if (::GetLastError() == ERROR_NO_ASSOCIATION)
|
| - return OpenItemWithExternalApp(full_path);
|
| + // Show the Windows "Open With" dialog box to ask the user to pick an app to
|
| + // open the file with. Note that we are not forwarding |args| for the "openas"
|
| + // call since the target application is nolonger known at this point.
|
| + if (open_result == ERROR_NO_ASSOCIATION)
|
| + return InvokeShellExecute(full_path, directory, base::string16(), L"openas",
|
| + kDefaultOpenAsFlags) == ERROR_SUCCESS;
|
| return false;
|
| }
|
|
|
| -bool OpenItemViaShell(const base::FilePath& full_path) {
|
| +bool OpenFileViaShell(const base::FilePath& full_path) {
|
| return OpenAnyViaShell(full_path.value(), full_path.DirName().value(),
|
| - base::string16(), 0);
|
| + base::string16(), kDefaultOpenFlags);
|
| +}
|
| +
|
| +bool OpenFolderViaShell(const base::FilePath& full_path) {
|
| + // The "explore" verb causes the folder at |full_path| to be displayed in a
|
| + // file browser. This will fail if |full_path| is not a directory. The
|
| + // resulting error does not cause UI due to the SEE_MASK_FLAG_NO_UI flag in
|
| + // kDefaultOpenFlags.
|
| + return InvokeShellExecute(full_path.value(), full_path.value(),
|
| + base::string16(), L"explore",
|
| + kDefaultOpenFlags) == ERROR_SUCCESS;
|
| }
|
|
|
| bool PreventWindowFromPinning(HWND hwnd) {
|
|
|