blob: 2a6016ded41b37a1d8c1848d688d109c520cfd17 [file] [log] [blame]
// Copyright 2008-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
#include "omaha/worker/ping_utils.h"
#include <atlstr.h>
#include "omaha/common/debug.h"
#include "omaha/common/logging.h"
#include "omaha/common/omaha_version.h"
#include "omaha/common/utils.h"
#include "omaha/goopdate/command_line.h"
#include "omaha/worker/application_data.h"
#include "omaha/worker/application_manager.h"
#include "omaha/worker/app_request.h"
#include "omaha/worker/app_request_data.h"
#include "omaha/worker/job.h"
#include "omaha/worker/ping.h"
#include "omaha/worker/ping_event.h"
#include "omaha/worker/product_data.h"
namespace omaha {
namespace ping_utils {
// If version is NULL, the current version will be used.
HRESULT SendGoopdatePing(bool is_machine,
const CommandLineExtraArgs& extra_args,
const CString& install_source,
PingEvent::Types type,
HRESULT result,
int extra_code1,
const TCHAR* version,
Ping* ping) {
CORE_LOG(L2, (_T("[SendGoopdatePing]")));
ASSERT1(ping);
CString previous_version;
AppRequestData app_request_data_goopdate;
BuildGoogleUpdateAppRequestData(is_machine,
extra_args,
install_source,
&previous_version,
&app_request_data_goopdate);
PingEvent::Results event_result = (S_OK == result) ?
PingEvent::EVENT_RESULT_SUCCESS :
PingEvent::EVENT_RESULT_ERROR;
PingEvent ping_event(type,
event_result,
result,
extra_code1,
previous_version);
app_request_data_goopdate.AddPingEvent(ping_event);
Request request(is_machine);
if (version) {
request.set_version(version);
}
AppRequest app_request(app_request_data_goopdate);
request.AddAppRequest(app_request);
HRESULT hr = ping->SendPing(&request);
if (FAILED(hr)) {
CORE_LOG(LE, (_T("[SendPing failed][0x%08x]"), hr));
return hr;
}
return S_OK;
}
// Initializes an AppRequest structure with information about
// GoogleUpdate. If extra contains data, its values are used. Otherwise,
// attempts to obtain data from the registry.
void BuildGoogleUpdateAppRequestData(bool is_machine,
const CommandLineExtraArgs& extra_args,
const CString& install_source,
CString* previous_version,
AppRequestData* app_request_data) {
CORE_LOG(L3, (_T("[Ping::BuildGoogleUpdateAppRequest]")));
ASSERT1(app_request_data);
if (previous_version) {
*previous_version = _T("");
}
AppData app_data_goopdate(kGoopdateGuid, is_machine);
app_data_goopdate.set_version(GetVersionString());
AppManager app_manager(is_machine);
ProductData product_data;
// TODO(omaha): Should we just call ReadAppDataFromStore?
HRESULT hr = app_manager.ReadProductDataFromStore(kGoopdateGuid,
&product_data);
if (SUCCEEDED(hr)) {
if (previous_version) {
*previous_version = product_data.app_data().previous_version();
}
app_data_goopdate.set_iid(product_data.app_data().iid());
app_data_goopdate.set_brand_code(product_data.app_data().brand_code());
app_data_goopdate.set_client_id(product_data.app_data().client_id());
app_data_goopdate.set_did_run(product_data.app_data().did_run());
} else {
CORE_LOG(LEVEL_WARNING, (_T("[ReadProductDataFromStore failed]")
_T("[0x%x][%s]"), hr, kGoogleUpdateAppId));
// Use branding data from the command line if present.
// We do not want to use branding data from the command line if this is not
// the first install of Google Update.
if (!extra_args.brand_code.IsEmpty()) {
app_data_goopdate.set_brand_code(extra_args.brand_code);
}
if (!extra_args.client_id.IsEmpty()) {
app_data_goopdate.set_client_id(extra_args.client_id);
}
}
// Always use the installation ID and install source from the command line if
// present.
if (GUID_NULL != extra_args.installation_id) {
app_data_goopdate.set_iid(extra_args.installation_id);
}
app_data_goopdate.set_install_source(install_source);
AppRequestData app_request_data_temp(app_data_goopdate);
*app_request_data = app_request_data_temp;
}
HRESULT SendPostSetupPing(HRESULT result,
int extra_code1,
const CString& previous_version,
bool is_machine,
bool is_self_update,
const CommandLineExtraArgs& extra,
const CString& install_source,
Ping* ping) {
CORE_LOG(L3, (_T("[Ping::SendPostSetupPing]")));
ASSERT1(ping);
scoped_ptr<Request> request(new Request(is_machine));
AppRequestData app_request_data;
BuildGoogleUpdateAppRequestData(
is_machine,
extra,
install_source,
NULL,
&app_request_data);
const PingEvent::Results event_result = (S_OK == result) ?
PingEvent::EVENT_RESULT_SUCCESS :
PingEvent::EVENT_RESULT_ERROR;
const PingEvent::Types type = is_self_update ?
PingEvent::EVENT_SETUP_UPDATE_COMPLETE :
PingEvent::EVENT_SETUP_INSTALL_COMPLETE;
PingEvent ping_event(type,
event_result,
result,
extra_code1,
previous_version);
app_request_data.AddPingEvent(ping_event);
if (is_self_update) {
// In case of self updates we also indicate that we completed the update
// job started by the previous version of Omaha.
PingEvent ping_event2(PingEvent::EVENT_UPDATE_COMPLETE,
event_result,
result,
extra_code1,
previous_version);
app_request_data.AddPingEvent(ping_event2);
}
AppRequest app_request(app_request_data);
request->AddAppRequest(app_request);
HRESULT hr = ping->SendPing(request.get());
if (FAILED(hr)) {
CORE_LOG(LE, (_T("[SendSetupPing(completed) failed][0x%08x]"), hr));
return hr;
}
return S_OK;
}
PingEvent::Results CompletionStatusToPingEventResult(
JobCompletionStatus status) {
PingEvent::Results result = PingEvent::EVENT_RESULT_ERROR;
switch (status) {
case COMPLETION_SUCCESS:
result = PingEvent::EVENT_RESULT_SUCCESS;
break;
case COMPLETION_SUCCESS_REBOOT_REQUIRED:
result = PingEvent::EVENT_RESULT_SUCCESS_REBOOT;
break;
case COMPLETION_ERROR:
result = PingEvent::EVENT_RESULT_ERROR;
break;
case COMPLETION_INSTALLER_ERROR_MSI:
result = PingEvent::EVENT_RESULT_INSTALLER_ERROR_MSI;
break;
case COMPLETION_INSTALLER_ERROR_SYSTEM:
result = PingEvent::EVENT_RESULT_INSTALLER_ERROR_SYSTEM;
break;
case COMPLETION_INSTALLER_ERROR_OTHER:
result = PingEvent::EVENT_RESULT_INSTALLER_ERROR_OTHER;
break;
case COMPLETION_CANCELLED:
result = PingEvent::EVENT_RESULT_CANCELLED;
break;
default:
ASSERT1(false);
break;
}
return result;
}
HRESULT BuildCompletedPingForAllProducts(const ProductDataVector& products,
bool is_update,
const CompletionInfo& info,
Request* request) {
CORE_LOG(L2, (_T("[BuildCompletedPingForAllProducts]")));
ASSERT1(request);
PingEvent::Types type = is_update ? PingEvent::EVENT_UPDATE_COMPLETE :
PingEvent::EVENT_INSTALL_COMPLETE;
PingEvent::Results result = CompletionStatusToPingEventResult(info.status);
for (size_t i = 0; i < products.size(); ++i) {
const ProductData& product_data = products[i];
AppRequestData app_request_data(product_data.app_data());
// Create and add the ping event.
CString previous_version = app_request_data.app_data().previous_version();
// TODO(omaha): Remove this value when circular log buffer is implemented.
// This value must not be a valid Job::JobState.
const int kAppProductsPingJobState = 0xff;
PingEvent ping_event(type,
result,
info.error_code,
Job::kJobStateExtraCodeMask | kAppProductsPingJobState,
previous_version);
app_request_data.AddPingEvent(ping_event);
AppRequest app_request(app_request_data);
request->AddAppRequest(app_request);
}
ASSERT1(products.size() ==
static_cast<size_t>(request->get_request_count()));
return S_OK;
}
HRESULT SendCompletedPingsForAllProducts(const ProductDataVector& products,
bool is_machine,
bool is_update,
const CompletionInfo& info,
Ping* ping) {
CORE_LOG(L2, (_T("[SendCompletedPingsForAllProducts]")));
ASSERT1(ping);
scoped_ptr<Request> request(new Request(is_machine));
HRESULT hr = BuildCompletedPingForAllProducts(products,
is_update,
info,
request.get());
if (FAILED(hr)) {
CORE_LOG(LE, (_T("[BuildCompletedPingForAllProducts failed][0x%08x]"), hr));
return hr;
}
if (!products.empty()) {
HRESULT hr = ping->SendPing(request.get());
if (FAILED(hr)) {
CORE_LOG(LE, (_T("[SendPing failed][0x%08x]"), hr));
return hr;
}
}
return S_OK;
}
} // namespace ping_utils
} // namespace omaha