default_apps_util.cc 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. // Copyright 2022 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. #include "base/win/default_apps_util.h"
  5. #include <shobjidl.h>
  6. #include <wrl/client.h>
  7. #include "base/logging.h"
  8. #include "base/strings/strcat.h"
  9. #include "base/strings/string_util.h"
  10. #include "base/win/windows_version.h"
  11. namespace {
  12. // Returns the target used as a activate parameter when opening the settings
  13. // pointing to the page that is the most relevant to a user trying to change the
  14. // default handler for `protocol`.
  15. std::wstring GetTargetForDefaultAppsSettings(base::WStringPiece protocol) {
  16. static constexpr base::WStringPiece kSystemSettingsDefaultAppsPrefix(
  17. L"SystemSettings_DefaultApps_");
  18. if (base::EqualsCaseInsensitiveASCII(protocol, L"http"))
  19. return base::StrCat({kSystemSettingsDefaultAppsPrefix, L"Browser"});
  20. if (base::EqualsCaseInsensitiveASCII(protocol, L"mailto"))
  21. return base::StrCat({kSystemSettingsDefaultAppsPrefix, L"Email"});
  22. return L"SettingsPageAppsDefaultsProtocolView";
  23. }
  24. } // namespace
  25. namespace base::win {
  26. bool CanLaunchDefaultAppsSettingsModernDialog() {
  27. return GetVersion() >= Version::WIN8;
  28. }
  29. bool LaunchDefaultAppsSettingsModernDialog(base::WStringPiece protocol) {
  30. // The appModelId looks arbitrary but it is the same in Win8 and Win10. There
  31. // is no easy way to retrieve the appModelId from the registry.
  32. static constexpr wchar_t kControlPanelAppModelId[] =
  33. L"windows.immersivecontrolpanel_cw5n1h2txyewy"
  34. L"!microsoft.windows.immersivecontrolpanel";
  35. if (!CanLaunchDefaultAppsSettingsModernDialog())
  36. return false;
  37. Microsoft::WRL::ComPtr<IApplicationActivationManager> activator;
  38. HRESULT hr = ::CoCreateInstance(CLSID_ApplicationActivationManager, nullptr,
  39. CLSCTX_ALL, IID_PPV_ARGS(&activator));
  40. if (FAILED(hr))
  41. return false;
  42. DWORD pid = 0;
  43. CoAllowSetForegroundWindow(activator.Get(), nullptr);
  44. hr = activator->ActivateApplication(
  45. kControlPanelAppModelId, L"page=SettingsPageAppsDefaults", AO_NONE, &pid);
  46. if (FAILED(hr))
  47. return false;
  48. if (protocol.empty())
  49. return true;
  50. hr = activator->ActivateApplication(
  51. kControlPanelAppModelId,
  52. base::StrCat({L"page=SettingsPageAppsDefaults&target=",
  53. GetTargetForDefaultAppsSettings(protocol)})
  54. .c_str(),
  55. AO_NONE, &pid);
  56. return SUCCEEDED(hr);
  57. }
  58. } // namespace base::win