summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-23 08:27:43 +0000
committervitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-23 08:27:43 +0000
commit17ac9a41a5febde114e988b02e3bb1decb15c62d (patch)
tree4c75bb9211ac10a12d810061a6dbb1e5e82d7b20
parent342a79f2385be0c176cc9a175709061ab91a35ad (diff)
downloadchromium_src-17ac9a41a5febde114e988b02e3bb1decb15c62d.zip
chromium_src-17ac9a41a5febde114e988b02e3bb1decb15c62d.tar.gz
chromium_src-17ac9a41a5febde114e988b02e3bb1decb15c62d.tar.bz2
Added Cloud Print Service installer/uninstaller.
Added Google Update integration. R=gene BUG=229183 NOTRY=true Review URL: https://chromiumcodereview.appspot.com/14358019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195765 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cloud_print/service/service.gyp4
-rw-r--r--cloud_print/service/service_constants.cc10
-rw-r--r--cloud_print/service/service_constants.h13
-rw-r--r--cloud_print/service/service_switches.cc1
-rw-r--r--cloud_print/service/service_switches.h1
-rw-r--r--cloud_print/service/win/chrome_launcher.cc14
-rw-r--r--cloud_print/service/win/cloud_print_service.cc5
-rw-r--r--cloud_print/service/win/cloud_print_service_config.cc8
-rw-r--r--cloud_print/service/win/installer.cc125
-rw-r--r--cloud_print/service/win/installer.h15
-rw-r--r--cloud_print/service/win/service_controller.cc62
-rw-r--r--cloud_print/service/win/service_controller.h8
-rw-r--r--cloud_print/service/win/service_resources.grd3
13 files changed, 251 insertions, 18 deletions
diff --git a/cloud_print/service/service.gyp b/cloud_print/service/service.gyp
index 9b5bb5bef..17384c7 100644
--- a/cloud_print/service/service.gyp
+++ b/cloud_print/service/service.gyp
@@ -75,6 +75,8 @@
'<(DEPTH)/content/public/common/content_switches.cc',
'<(DEPTH)/cloud_print/common/win/cloud_print_utils.cc',
'<(DEPTH)/cloud_print/common/win/cloud_print_utils.h',
+ 'service_constants.cc',
+ 'service_constants.h',
'service_state.cc',
'service_state.h',
'service_switches.cc',
@@ -122,6 +124,8 @@
'sources': [
'<(SHARED_INTERMEDIATE_DIR)/cloud_print/cloud_print_service_config_exe_version.rc',
'win/cloud_print_service_config.cc',
+ 'win/installer.cc',
+ 'win/installer.h',
],
'includes': [
'win/service_resources.gypi'
diff --git a/cloud_print/service/service_constants.cc b/cloud_print/service/service_constants.cc
new file mode 100644
index 0000000..74b51f8
--- /dev/null
+++ b/cloud_print/service/service_constants.cc
@@ -0,0 +1,10 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cloud_print/service/service_constants.h"
+
+const wchar_t kGoogleUpdateId[] = L"{86206CC6-CD3C-427D-9A34-77B34819CDD3}";
+
+const wchar_t kSubDirectory[] = L"Google\\Cloud Print Service";
+
diff --git a/cloud_print/service/service_constants.h b/cloud_print/service/service_constants.h
new file mode 100644
index 0000000..75dfec2
--- /dev/null
+++ b/cloud_print/service/service_constants.h
@@ -0,0 +1,13 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CLOUD_PRINT_SERVICE_SERVICE_CONSTANTS_H_
+#define CLOUD_PRINT_SERVICE_SERVICE_CONSTANTS_H_
+
+extern const wchar_t kGoogleUpdateId[];
+
+extern const wchar_t kSubDirectory[];
+
+#endif // CLOUD_PRINT_SERVICE_SERVICE_CONSTANTS_H_
+
diff --git a/cloud_print/service/service_switches.cc b/cloud_print/service/service_switches.cc
index 9386777..72afdd0 100644
--- a/cloud_print/service/service_switches.cc
+++ b/cloud_print/service/service_switches.cc
@@ -5,6 +5,7 @@
#include "cloud_print/service/service_switches.h"
const char kConsoleSwitch[] = "console";
+const char kDeleteSwitch[] = "delete";
const char kInstallSwitch[] = "install";
const char kRequirementsSwitch[] = "requirements";
const char kServiceSwitch[] = "service";
diff --git a/cloud_print/service/service_switches.h b/cloud_print/service/service_switches.h
index ae92fed..b6e11e4 100644
--- a/cloud_print/service/service_switches.h
+++ b/cloud_print/service/service_switches.h
@@ -6,6 +6,7 @@
#define CLOUD_PRINT_SERVICE_SERVICE_SWITCHES_H_
extern const char kConsoleSwitch[];
+extern const char kDeleteSwitch[];
extern const char kInstallSwitch[];
extern const char kRequirementsSwitch[];
extern const char kServiceSwitch[];
diff --git a/cloud_print/service/win/chrome_launcher.cc b/cloud_print/service/win/chrome_launcher.cc
index 831af6f..6c5bbc5 100644
--- a/cloud_print/service/win/chrome_launcher.cc
+++ b/cloud_print/service/win/chrome_launcher.cc
@@ -20,6 +20,8 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/installer/launcher_support/chrome_launcher_support.h"
+#include "cloud_print/common/win/cloud_print_utils.h"
+#include "cloud_print/service/service_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "googleurl/src/gurl.h"
#include "net/base/url_util.h"
@@ -27,6 +29,7 @@
namespace {
const int kShutdownTimeoutMs = 30 * 1000;
+const int kUsageUpdateTimeoutMs = 6 * 3600 * 1000; // 6 hours.
static const char16 kAutoRunKeyPath[] =
L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
@@ -202,10 +205,14 @@ void ChromeLauncher::Run() {
base::Time started = base::Time::Now();
DWORD thread_id = 0;
LaunchProcess(cmd, chrome_handle.Receive(), &thread_id);
- int exit_code = 0;
+
HANDLE handles[] = {stop_event_.handle(), chrome_handle};
- DWORD wait_result = ::WaitForMultipleObjects(arraysize(handles), handles,
- FALSE, INFINITE);
+ DWORD wait_result = WAIT_TIMEOUT;
+ while (wait_result == WAIT_TIMEOUT) {
+ cloud_print::SetGoogleUpdateUsage(kGoogleUpdateId);
+ wait_result = ::WaitForMultipleObjects(arraysize(handles), handles,
+ FALSE, kUsageUpdateTimeoutMs);
+ }
if (wait_result == WAIT_OBJECT_0) {
ShutdownChrome(chrome_handle, thread_id);
break;
@@ -289,7 +296,6 @@ std::string ChromeLauncher::CreateServiceStateFile(
return result;
}
- int exit_code = 0;
DWORD wait_result = ::WaitForSingleObject(chrome_handle, INFINITE);
if (wait_result != WAIT_OBJECT_0) {
LOG(ERROR) << "Chrome launch failed.";
diff --git a/cloud_print/service/win/cloud_print_service.cc b/cloud_print/service/win/cloud_print_service.cc
index dd20668..f29d4e7 100644
--- a/cloud_print/service/win/cloud_print_service.cc
+++ b/cloud_print/service/win/cloud_print_service.cc
@@ -20,6 +20,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "cloud_print/common/win/cloud_print_utils.h"
+#include "cloud_print/service/service_constants.h"
#include "cloud_print/service/service_state.h"
#include "cloud_print/service/service_switches.h"
#include "cloud_print/service/win/chrome_launcher.h"
@@ -30,8 +31,6 @@
namespace {
-const wchar_t kAppDataSubDir[] = L"Google\\Cloud Print Service";
-
void InvalidUsage() {
base::FilePath service_path;
CHECK(PathService::Get(base::FILE_EXE, &service_path));
@@ -367,7 +366,7 @@ class CloudPrintServiceModule
return user_data_dir_switch_;
base::FilePath result;
CHECK(PathService::Get(base::DIR_LOCAL_APP_DATA, &result));
- return result.Append(kAppDataSubDir);
+ return result.Append(kSubDirectory);
}
static BOOL WINAPI ConsoleCtrlHandler(DWORD type);
diff --git a/cloud_print/service/win/cloud_print_service_config.cc b/cloud_print/service/win/cloud_print_service_config.cc
index eff74f7..84598b5 100644
--- a/cloud_print/service/win/cloud_print_service_config.cc
+++ b/cloud_print/service/win/cloud_print_service_config.cc
@@ -17,6 +17,7 @@
#include "cloud_print/resources.h"
#include "cloud_print/service/service_state.h"
#include "cloud_print/service/win/chrome_launcher.h"
+#include "cloud_print/service/win/installer.h"
#include "cloud_print/service/win/service_controller.h"
#include "cloud_print/service/win/service_utils.h"
#include "cloud_print/service/win/setup_listener.h"
@@ -201,8 +202,7 @@ LRESULT SetupDialog::OnInitDialog(UINT message, WPARAM wparam, LPARAM lparam,
ATLVERIFY(CenterWindow());
WTL::CIcon icon;
- if (icon.LoadIcon(MAKEINTRESOURCE(IDI_ICON), GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON), 0)) {
+ if (icon.LoadIcon(MAKEINTRESOURCE(IDI_ICON))) {
SetIcon(icon);
}
@@ -428,6 +428,10 @@ int WINAPI WinMain(__in HINSTANCE hInstance,
base::AtExitManager at_exit;
CommandLine::Init(0, NULL);
+ HRESULT result = ProcessInstallerSwitches();
+ if (result != S_FALSE)
+ return result;
+
MessageLoopForUI loop;
scoped_refptr<SetupDialog> dialog(new SetupDialog());
dialog->Create(NULL);
diff --git a/cloud_print/service/win/installer.cc b/cloud_print/service/win/installer.cc
new file mode 100644
index 0000000..c82b1c8
--- /dev/null
+++ b/cloud_print/service/win/installer.cc
@@ -0,0 +1,125 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cloud_print/service/win/installer.h"
+
+#include <winerror.h>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/win/scoped_com_initializer.h"
+#include "base/win/shortcut.h"
+#include "cloud_print/common/win/cloud_print_utils.h"
+#include "cloud_print/common/win/install_utils.h"
+#include "cloud_print/service/service_constants.h"
+#include "cloud_print/service/service_switches.h"
+#include "cloud_print/service/win/service_controller.h"
+
+namespace {
+
+base::FilePath GetShortcutPath(int dir_key, bool with_subdir) {
+ base::FilePath path;
+ if (!PathService::Get(dir_key, &path))
+ return base::FilePath();
+ path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME));
+ if (with_subdir)
+ path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME));
+ return path.InsertBeforeExtension(L".lnk");
+}
+
+void CreateShortcut(int dir_key, bool with_subdir,
+ base::win::ShortcutOperation operation) {
+ base::FilePath path = GetShortcutPath(dir_key, with_subdir);
+ if (path.empty())
+ return;
+ file_util::CreateDirectory(path.DirName());
+ base::win::ShortcutProperties properties;
+
+ base::FilePath exe_path;
+ if (!PathService::Get(base::FILE_EXE, &exe_path))
+ return;
+ properties.set_target(exe_path);
+ properties.set_working_dir(exe_path.DirName());
+ CreateOrUpdateShortcutLink(path, properties, operation);
+}
+
+void CreateShortcuts(bool create_always) {
+ base::win::ScopedCOMInitializer co_init;
+ base::win::ShortcutOperation operation =
+ create_always ? base::win::SHORTCUT_CREATE_ALWAYS :
+ base::win::SHORTCUT_REPLACE_EXISTING;
+ CreateShortcut(base::DIR_COMMON_START_MENU, true, operation);
+ CreateShortcut(base::DIR_COMMON_DESKTOP, false, operation);
+}
+
+void DeleteShortcut(int dir_key, bool with_subdir) {
+ base::FilePath path = GetShortcutPath(dir_key, with_subdir);
+ if (path.empty())
+ return;
+ if (with_subdir)
+ file_util::Delete(path.DirName(), true);
+ else
+ file_util::Delete(path, false);
+}
+
+void DeleteShortcuts() {
+ DeleteShortcut(base::DIR_COMMON_START_MENU, true);
+ DeleteShortcut(base::DIR_COMMON_DESKTOP, false);
+}
+
+} // namespace
+
+HRESULT ProcessInstallerSwitches() {
+ const CommandLine& command_line(*CommandLine::ForCurrentProcess());
+
+ if (command_line.HasSwitch(kInstallSwitch)) {
+ base::FilePath old_location =
+ cloud_print::GetInstallLocation(kGoogleUpdateId);
+
+ cloud_print::CreateUninstallKey(
+ kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME),
+ kUninstallSwitch);
+
+ ServiceController controller(cloud_print::LoadLocalString(IDS_SERVICENAME));
+ HRESULT hr = controller.UpdateBinaryPath();
+ if (FAILED(hr))
+ return hr;
+
+ if (!old_location.empty() &&
+ cloud_print::IsProgramsFilesParent(old_location) &&
+ old_location != cloud_print::GetInstallLocation(kGoogleUpdateId)) {
+ file_util::Delete(old_location, true);
+ }
+
+ cloud_print::SetGoogleUpdateKeys(
+ kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME));
+
+ CreateShortcuts(old_location.empty());
+
+ return S_OK;
+ } else if (command_line.HasSwitch(kUninstallSwitch)) {
+ ServiceController controller(cloud_print::LoadLocalString(IDS_SERVICENAME));
+ HRESULT hr = controller.UninstallService();
+ if (FAILED(hr))
+ return hr;
+
+ DeleteShortcuts();
+
+ cloud_print::DeleteGoogleUpdateKeys(kGoogleUpdateId);
+ cloud_print::DeleteUninstallKey(kGoogleUpdateId);
+ cloud_print::DeleteProgramDir(kDeleteSwitch);
+ return S_OK;
+ } else if (command_line.HasSwitch(kDeleteSwitch)) {
+ base::FilePath delete_path = command_line.GetSwitchValuePath(kDeleteSwitch);
+ if (!delete_path.empty() &&
+ cloud_print::IsProgramsFilesParent(delete_path)) {
+ file_util::Delete(delete_path, true);
+ }
+ return S_OK;
+ }
+
+ return S_FALSE;
+}
+
diff --git a/cloud_print/service/win/installer.h b/cloud_print/service/win/installer.h
new file mode 100644
index 0000000..027e97b
--- /dev/null
+++ b/cloud_print/service/win/installer.h
@@ -0,0 +1,15 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CLOUD_PRINT_SERVICE_INSTALLER_H_
+#define CLOUD_PRINT_SERVICE_INSTALLER_H_
+
+#include <wtypes.h>
+
+// Installs/uninstalls product if related switches provided.
+// Returns S_OK on success or error code.
+// Returns S_FALE if no related switches were provided.
+HRESULT ProcessInstallerSwitches();
+
+#endif // CLOUD_PRINT_SERVICE_INSTALLER_H_ \ No newline at end of file
diff --git a/cloud_print/service/win/service_controller.cc b/cloud_print/service/win/service_controller.cc
index dd643d1..3b748d1 100644
--- a/cloud_print/service/win/service_controller.cc
+++ b/cloud_print/service/win/service_controller.cc
@@ -15,6 +15,7 @@
#include "base/win/scoped_handle.h"
#include "chrome/common/chrome_switches.h"
#include "cloud_print/common/win/cloud_print_utils.h"
+#include "cloud_print/service/service_constants.h"
#include "cloud_print/service/service_switches.h"
#include "cloud_print/service/win/chrome_launcher.h"
#include "cloud_print/service/win/local_security_policy.h"
@@ -80,7 +81,7 @@ HRESULT OpenService(const string16& name, DWORD access,
} // namespace
ServiceController::ServiceController(const string16& name)
- : name_(name) {
+ : name_(name), command_line_(CommandLine::NO_PROGRAM) {
}
ServiceController::~ServiceController() {
@@ -119,6 +120,12 @@ HRESULT ServiceController::StopService() {
return S_OK;
}
+base::FilePath ServiceController::GetBinary() const {
+ base::FilePath service_path;
+ CHECK(PathService::Get(base::FILE_EXE, &service_path));
+ return service_path.DirName().Append(base::FilePath(kServiceExeName));
+}
+
HRESULT ServiceController::InstallConnectorService(
const string16& user,
const string16& password,
@@ -152,9 +159,7 @@ HRESULT ServiceController::InstallService(const string16& user,
if (FAILED(hr))
return hr;
- base::FilePath service_path;
- CHECK(PathService::Get(base::FILE_EXE, &service_path));
- service_path = service_path.DirName().Append(base::FilePath(kServiceExeName));
+ base::FilePath service_path = GetBinary();
if (!file_util::PathExists(service_path))
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
CommandLine command_line(service_path);
@@ -218,12 +223,49 @@ HRESULT ServiceController::UninstallService() {
return hr;
}
-void ServiceController::UpdateState() {
+HRESULT ServiceController::UpdateBinaryPath() {
+ UpdateState();
+ ServiceController::State origina_state = state();
+ if (origina_state < ServiceController::STATE_STOPPED)
+ return S_FALSE;
+
ServiceHandle service;
+ HRESULT hr = OpenService(name_, SERVICE_CHANGE_CONFIG, &service);
+ if (FAILED(hr))
+ return hr;
+
+ base::FilePath service_path = GetBinary();
+ if (!file_util::PathExists(service_path))
+ return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+
+ command_line_.SetProgram(service_path);
+ if (!::ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
+ SERVICE_NO_CHANGE,
+ command_line_.GetCommandLineString().c_str(), NULL,
+ NULL, NULL, NULL, NULL, NULL)) {
+ return cloud_print::GetLastHResult();
+ }
+
+ if (origina_state != ServiceController::STATE_RUNNING)
+ return S_OK;
+
+ hr = StopService();
+ if (FAILED(hr))
+ return hr;
+
+ hr = StartService();
+ if (FAILED(hr))
+ return hr;
+
+ return S_OK;
+}
+
+void ServiceController::UpdateState() {
state_ = STATE_NOT_FOUND;
user_.clear();
is_logging_enabled_ = false;
+ ServiceHandle service;
HRESULT hr = OpenService(name_, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG,
&service);
if (FAILED(hr))
@@ -249,11 +291,15 @@ void ServiceController::UpdateState() {
return;
}
- CommandLine command_line(CommandLine::FromString(config->lpBinaryPathName));
- if (!command_line.HasSwitch(kServiceSwitch)) {
+ command_line_ = CommandLine::FromString(config->lpBinaryPathName);
+ if (!command_line_.HasSwitch(kServiceSwitch)) {
state_ = STATE_NOT_FOUND;
return;
}
- is_logging_enabled_ = command_line.HasSwitch(switches::kEnableLogging);
+ is_logging_enabled_ = command_line_.HasSwitch(switches::kEnableLogging);
user_ = config->lpServiceStartName;
}
+
+bool ServiceController::is_logging_enabled() const {
+ return command_line_.HasSwitch(switches::kEnableLogging);
+}
diff --git a/cloud_print/service/win/service_controller.h b/cloud_print/service/win/service_controller.h
index d703c0a..ab95396 100644
--- a/cloud_print/service/win/service_controller.h
+++ b/cloud_print/service/win/service_controller.h
@@ -8,6 +8,7 @@
#include <atlbase.h>
#include <string>
+#include "base/command_line.h"
#include "base/string16.h"
#include "cloud_print/resources.h"
@@ -46,11 +47,15 @@ class ServiceController {
HRESULT StartService();
HRESULT StopService();
+ HRESULT UpdateBinaryPath();
+
// Query service status and options. Results accessible with getters below.
void UpdateState();
State state() const { return state_; }
const string16& user() const { return user_; }
- bool is_logging_enabled() const { return is_logging_enabled_; }
+ bool is_logging_enabled() const;
+
+ base::FilePath GetBinary() const;
private:
HRESULT InstallService(const string16& user,
@@ -64,6 +69,7 @@ class ServiceController {
State state_;
string16 user_;
bool is_logging_enabled_;
+ CommandLine command_line_;
};
#endif // CLOUD_PRINT_SERVICE_SERVICE_CONTROLLER_H_
diff --git a/cloud_print/service/win/service_resources.grd b/cloud_print/service/win/service_resources.grd
index 765f48f..a804e42 100644
--- a/cloud_print/service/win/service_resources.grd
+++ b/cloud_print/service/win/service_resources.grd
@@ -21,6 +21,9 @@ file.
<message name="IDS_SERVICENAME" translateable="false">
CloudPrintService
</message>
+ <message name="IDS_FULL_PRODUCT_NAME" translateable="false">
+ Google Cloud Print Service
+ </message>
<message name="IDS_SETUP_PROGRAM_NAME">
Service Options
</message>