15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/platform_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <commdlg.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dwmapi.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shellapi.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlobj.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/metrics/field_trial.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_co_mem.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_comptr.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/windows_version.h"
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h"
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/common/chrome_utility_messages.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/public/browser/utility_process_host.h"
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/utility_process_host_client.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/win/shell.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/native_widget_types.h"
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShowItemInFolderOnFileThread(const base::FilePath& full_path) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath dir = full_path.DirName().AsEndingWithSeparator();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ParseDisplayName will fail if the directory is "C:", it must be "C:\\".
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (dir.empty())
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef HRESULT (WINAPI *SHOpenFolderAndSelectItemsFuncPtr)(
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PCIDLIST_ABSOLUTE pidl_Folder,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UINT cidl,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PCUITEMID_CHILD_ARRAY pidls,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DWORD flags);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SHOpenFolderAndSelectItemsFuncPtr open_folder_and_select_itemsPtr =
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool initialize_open_folder_proc = true;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (initialize_open_folder_proc) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initialize_open_folder_proc = false;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The SHOpenFolderAndSelectItems API is exposed by shell32 version 6
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and does not exist in Win2K. We attempt to retrieve this function export
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // from shell32 and if it does not exist, we just invoke ShellExecute to
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // open the folder thus losing the functionality to select the item in
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the process.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HMODULE shell32_base = GetModuleHandle(L"shell32.dll");
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!shell32_base) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << " " << __FUNCTION__ << "(): Can't open shell32.dll";
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    open_folder_and_select_itemsPtr =
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<SHOpenFolderAndSelectItemsFuncPtr>
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (GetProcAddress(shell32_base, "SHOpenFolderAndSelectItems"));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!open_folder_and_select_itemsPtr) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IShellFolder> desktop;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = SHGetDesktopFolder(desktop.Receive());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr))
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedCoMem<ITEMIDLIST> dir_item;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = desktop->ParseDisplayName(NULL, NULL,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const_cast<wchar_t *>(dir.value().c_str()),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 NULL, &dir_item, NULL);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr))
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedCoMem<ITEMIDLIST> file_item;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = desktop->ParseDisplayName(NULL, NULL,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const_cast<wchar_t *>(full_path.value().c_str()),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL, &file_item, NULL);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr))
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const ITEMIDLIST* highlight[] = { file_item };
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = (*open_folder_and_select_itemsPtr)(dir_item, arraysize(highlight),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          highlight, NULL);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On some systems, the above call mysteriously fails with "file not
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // found" even though the file is there.  In these cases, ShellExecute()
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // seems to work as a fallback (although it won't select the file).
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (hr == ERROR_FILE_NOT_FOUND) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << " " << __FUNCTION__
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "(): Can't open full_path = \""
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << full_path.value() << "\""
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                  << " hr = " << logging::SystemErrorCodeToString(hr);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Old ShellExecute crashes the process when the command for a given scheme
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is empty. This function tells if it is.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ValidateShellCommandForScheme(const std::string& scheme) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::win::RegKey key;
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::wstring registry_path = base::ASCIIToWide(scheme) +
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               L"\\shell\\open\\command";
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  key.Open(HKEY_CLASSES_ROOT, registry_path.c_str(), KEY_READ);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!key.Valid())
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DWORD size = 0;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  key.ReadValue(NULL, NULL, &size, NULL);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size <= 2)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OpenExternalOnFileThread(const GURL& url) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Quote the input scheme to be sure that the command does not have
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parameters unexpected by the external program. This url should already
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have been escaped.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string escaped_url = url.spec();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  escaped_url.insert(0, "\"");
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  escaped_url += "\"";
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // support URLS of 2083 chars in length, 2K is safe."
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kMaxUrlLength = 2048;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (escaped_url.length() > kMaxUrlLength) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_WIN7) {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!ValidateShellCommandForScheme(url.scheme()))
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(NULL, "open",
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                escaped_url.c_str(), NULL, NULL,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                SW_SHOWNORMAL)) <= 32) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We fail to execute the call. We could display a message to the user.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(nsylvain): we should also add a dialog to warn on errors. See
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // bug 1136923.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void OpenItemViaShellInUtilityProcess(const base::FilePath& full_path) {
16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::WeakPtr<content::UtilityProcessHost> utility_process_host(
16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      content::UtilityProcessHost::Create(NULL, NULL)->AsWeakPtr());
16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  utility_process_host->DisableSandbox();
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  utility_process_host->Send(new ChromeUtilityMsg_OpenItemViaShell(full_path));
16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace platform_util {
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) {
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH)
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome::ActivateDesktopHelper(chrome::ASH_KEEP_RUNNING);
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&ShowItemInFolderOnFileThread, full_path));
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OpenItem(Profile* profile, const base::FilePath& full_path) {
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH)
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome::ActivateDesktopHelper(chrome::ASH_KEEP_RUNNING);
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (base::FieldTrialList::FindFullName("IsolateShellOperations") ==
19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "Enabled") {
19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    BrowserThread::PostTask(
19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        BrowserThread::IO,
19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        FROM_HERE,
19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        base::Bind(&OpenItemViaShellInUtilityProcess, full_path));
19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  } else {
19603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    BrowserThread::PostTask(
19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        BrowserThread::FILE,
19803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        FROM_HERE,
19903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        base::Bind(base::IgnoreResult(&ui::win::OpenItemViaShell), full_path));
20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OpenExternal(Profile* profile, const GURL& url) {
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH &&
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !url.SchemeIsHTTPOrHTTPS())
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome::ActivateDesktopHelper(chrome::ASH_KEEP_RUNNING);
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          base::Bind(&OpenExternalOnFileThread, url));
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(USE_AURA)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::NativeWindow GetTopLevel(gfx::NativeView view) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ::GetAncestor(view, GA_ROOT);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::NativeView GetParent(gfx::NativeView view) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ::GetParent(view);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsWindowActive(gfx::NativeWindow window) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ::GetForegroundWindow() == window;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ActivateWindow(gfx::NativeWindow window) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::SetForegroundWindow(window);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsVisible(gfx::NativeView view) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MSVC complains if we don't include != 0.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ::IsWindowVisible(view) != 0;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace platform_util
238