Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / cloud_print / service / win / installer.cc
blob312af6e2c3382421a5fd10897c41c601ea42766e
1 // Copyright 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.
5 #include "cloud_print/service/win/installer.h"
7 #include <winerror.h>
9 #include "base/at_exit.h"
10 #include "base/command_line.h"
11 #include "base/files/file_util.h"
12 #include "base/path_service.h"
13 #include "base/win/scoped_com_initializer.h"
14 #include "base/win/shortcut.h"
15 #include "cloud_print/common/win/cloud_print_utils.h"
16 #include "cloud_print/common/win/install_utils.h"
17 #include "cloud_print/resources.h"
18 #include "cloud_print/service/service_constants.h"
19 #include "cloud_print/service/service_switches.h"
20 #include "cloud_print/service/win/service_controller.h"
22 namespace {
24 const wchar_t kConfigBinaryName[] = L"cloud_print_service_config.exe";
26 base::FilePath GetShortcutPath(int dir_key, bool with_subdir) {
27 base::FilePath path;
28 if (!PathService::Get(dir_key, &path))
29 return base::FilePath();
30 path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME));
31 if (with_subdir)
32 path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME));
33 return path.InsertBeforeExtension(L".lnk");
36 void CreateShortcut(int dir_key, bool with_subdir,
37 base::win::ShortcutOperation operation) {
38 base::FilePath path = GetShortcutPath(dir_key, with_subdir);
39 if (path.empty())
40 return;
41 base::CreateDirectory(path.DirName());
42 base::win::ShortcutProperties properties;
44 base::FilePath exe_path;
45 if (!PathService::Get(base::FILE_EXE, &exe_path))
46 return;
47 exe_path = exe_path.DirName().Append(base::FilePath(kConfigBinaryName));
48 properties.set_target(exe_path);
49 properties.set_working_dir(exe_path.DirName());
50 CreateOrUpdateShortcutLink(path, properties, operation);
53 void CreateShortcuts(bool create_always) {
54 base::win::ScopedCOMInitializer co_init;
55 base::win::ShortcutOperation operation =
56 create_always ? base::win::SHORTCUT_CREATE_ALWAYS :
57 base::win::SHORTCUT_REPLACE_EXISTING;
58 CreateShortcut(base::DIR_COMMON_START_MENU, true, operation);
59 CreateShortcut(base::DIR_COMMON_DESKTOP, false, operation);
62 void DeleteShortcut(int dir_key, bool with_subdir) {
63 base::FilePath path = GetShortcutPath(dir_key, with_subdir);
64 if (path.empty())
65 return;
66 if (with_subdir)
67 base::DeleteFile(path.DirName(), true);
68 else
69 base::DeleteFile(path, false);
72 void DeleteShortcuts() {
73 DeleteShortcut(base::DIR_COMMON_START_MENU, true);
74 DeleteShortcut(base::DIR_COMMON_DESKTOP, false);
77 } // namespace
79 HRESULT ProcessInstallerSwitches() {
80 const base::CommandLine& command_line(
81 *base::CommandLine::ForCurrentProcess());
83 if (command_line.HasSwitch(kInstallSwitch)) {
84 base::FilePath old_location =
85 cloud_print::GetInstallLocation(kGoogleUpdateId);
87 cloud_print::CreateUninstallKey(
88 kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME),
89 kUninstallSwitch);
91 ServiceController controller;
92 HRESULT hr = controller.UpdateBinaryPath();
93 if (FAILED(hr))
94 return hr;
96 if (!old_location.empty() &&
97 cloud_print::IsProgramsFilesParent(old_location) &&
98 old_location != cloud_print::GetInstallLocation(kGoogleUpdateId)) {
99 base::DeleteFile(old_location, true);
102 cloud_print::SetGoogleUpdateKeys(
103 kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME));
105 CreateShortcuts(old_location.empty());
107 return S_OK;
108 } else if (command_line.HasSwitch(kUninstallSwitch)) {
109 ServiceController controller;
110 HRESULT hr = controller.UninstallService();
111 if (FAILED(hr))
112 return hr;
114 DeleteShortcuts();
116 cloud_print::DeleteGoogleUpdateKeys(kGoogleUpdateId);
117 cloud_print::DeleteUninstallKey(kGoogleUpdateId);
118 cloud_print::DeleteProgramDir(kDeleteSwitch);
119 return S_OK;
120 } else if (command_line.HasSwitch(kDeleteSwitch)) {
121 base::FilePath delete_path = command_line.GetSwitchValuePath(kDeleteSwitch);
122 if (!delete_path.empty() &&
123 cloud_print::IsProgramsFilesParent(delete_path)) {
124 base::DeleteFile(delete_path, true);
126 return S_OK;
129 return S_FALSE;
132 class CloudPrintServiceSetupModule
133 : public ATL::CAtlExeModuleT<CloudPrintServiceSetupModule> {
136 CloudPrintServiceSetupModule _AtlModule;
138 int WINAPI WinMain(__in HINSTANCE hInstance,
139 __in HINSTANCE hPrevInstance,
140 __in LPSTR lpCmdLine,
141 __in int nCmdShow) {
142 base::AtExitManager at_exit;
143 base::CommandLine::Init(0, NULL);
144 return ProcessInstallerSwitches();