| OLD | NEW |
| (Empty) |
| 1 // Copyright 2009-2010 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 | |
| 16 #include "omaha/goopdate/app_state_checking_for_update.h" | |
| 17 #include "omaha/base/debug.h" | |
| 18 #include "omaha/base/error.h" | |
| 19 #include "omaha/base/logging.h" | |
| 20 #include "omaha/common/lang.h" | |
| 21 #include "omaha/common/update_response.h" | |
| 22 #include "omaha/goopdate/app_manager.h" | |
| 23 #include "omaha/goopdate/app_state_no_update.h" | |
| 24 #include "omaha/goopdate/app_state_update_available.h" | |
| 25 #include "omaha/goopdate/model.h" | |
| 26 #include "omaha/goopdate/server_resource.h" | |
| 27 #include "omaha/goopdate/string_formatter.h" | |
| 28 #include "omaha/goopdate/update_response_utils.h" | |
| 29 #include "omaha/goopdate/worker_metrics.h" | |
| 30 #include "omaha/goopdate/worker_utils.h" | |
| 31 | |
| 32 namespace omaha { | |
| 33 | |
| 34 namespace fsm { | |
| 35 | |
| 36 xml::UpdateResponseResult GetUpdateResponseResult( | |
| 37 const App* app, | |
| 38 const xml::UpdateResponse* update_response) { | |
| 39 ASSERT1(app); | |
| 40 ASSERT1(update_response); | |
| 41 | |
| 42 const CString language = app->app_bundle()->display_language(); | |
| 43 | |
| 44 xml::UpdateResponseResult update_response_result = | |
| 45 update_response_utils::GetResult(update_response, | |
| 46 app->app_guid_string(), | |
| 47 language); | |
| 48 | |
| 49 const bool is_omaha = !!::IsEqualGUID(kGoopdateGuid, app->app_guid()); | |
| 50 const bool has_update = update_response_result.first == S_OK && | |
| 51 app->is_update(); | |
| 52 | |
| 53 // Defer the update if the app is not Omaha, it has an update available, and | |
| 54 // an Omaha update is available at the same time. | |
| 55 if (!is_omaha && | |
| 56 has_update && | |
| 57 update_response_utils::IsOmahaUpdateAvailable(update_response)) { | |
| 58 StringFormatter formatter(language); | |
| 59 CString text; | |
| 60 VERIFY1(SUCCEEDED(formatter.LoadString(IDS_NO_UPDATE_RESPONSE, &text))); | |
| 61 update_response_result = std::make_pair(GOOPDATE_E_UPDATE_DEFERRED, text); | |
| 62 } | |
| 63 | |
| 64 return update_response_result; | |
| 65 } | |
| 66 | |
| 67 AppStateCheckingForUpdate::AppStateCheckingForUpdate() | |
| 68 : AppState(STATE_CHECKING_FOR_UPDATE), | |
| 69 update_response_(NULL) { | |
| 70 } | |
| 71 | |
| 72 // TODO(omaha3): Consider passing in an xml::response::App instead of a raw | |
| 73 // xml::UpdateResponse to this method. | |
| 74 void AppStateCheckingForUpdate::PostUpdateCheck( | |
| 75 App* app, | |
| 76 HRESULT update_check_result, | |
| 77 xml::UpdateResponse* update_response) { | |
| 78 CORE_LOG(L3, (_T("[AppStateCheckingForUpdate::PostUpdateCheck][0x%p]"), app)); | |
| 79 | |
| 80 ASSERT1(app); | |
| 81 ASSERT1(update_response); | |
| 82 | |
| 83 ASSERT1(app->model()->IsLockedByCaller()); | |
| 84 | |
| 85 update_response_ = update_response; | |
| 86 | |
| 87 const CString language = app->app_bundle()->display_language(); | |
| 88 | |
| 89 if (FAILED(update_check_result)) { | |
| 90 // TODO(omaha3): There is no guarantee that this is a actually network | |
| 91 // error. In Omaha 2, this was called much closer to the send. Making most | |
| 92 // errors, such as processing errors, app errors helps, but it could still | |
| 93 // be a parsing or other error. | |
| 94 CString error_message; | |
| 95 worker_utils::FormatMessageForNetworkError(update_check_result, | |
| 96 language, | |
| 97 &error_message); | |
| 98 | |
| 99 Error(app, ErrorContext(update_check_result), error_message); | |
| 100 return; | |
| 101 } | |
| 102 | |
| 103 PersistUpdateCheckSuccessfullySent(*app); | |
| 104 | |
| 105 const xml::UpdateResponseResult update_response_result( | |
| 106 GetUpdateResponseResult(app, update_response)); | |
| 107 | |
| 108 const HRESULT& code = update_response_result.first; | |
| 109 const CString& message = update_response_result.second; | |
| 110 | |
| 111 if (SUCCEEDED(code)) { | |
| 112 HandleUpdateAvailable(app, code, message); | |
| 113 } else if (code == GOOPDATE_E_UPDATE_DEFERRED) { | |
| 114 HandleUpdateDeferred(app, code, message); | |
| 115 } else if (code == GOOPDATE_E_NO_UPDATE_RESPONSE) { | |
| 116 HandleNoUpdate(app, code, message); | |
| 117 } else { | |
| 118 HandleErrorResponse(app, code, message); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 void AppStateCheckingForUpdate::HandleUpdateAvailable(App* app, | |
| 123 HRESULT code, | |
| 124 const CString& message) { | |
| 125 CORE_LOG(L3, (_T("[HandleUpdateAvailable][0x%p]"), app)); | |
| 126 | |
| 127 ASSERT1(app); | |
| 128 ASSERT1(SUCCEEDED(code)); | |
| 129 | |
| 130 UNREFERENCED_PARAMETER(code); | |
| 131 UNREFERENCED_PARAMETER(message); | |
| 132 | |
| 133 app->set_has_update_available(true); | |
| 134 | |
| 135 HRESULT hr = update_response_utils::BuildApp(update_response_, code, app); | |
| 136 if (FAILED(hr)) { | |
| 137 // Most of the errors that might actually be seen are likely to be due to | |
| 138 // response issues. Therefore, display a message about the server. | |
| 139 const CString language = app->app_bundle()->display_language(); | |
| 140 StringFormatter formatter(language); | |
| 141 CString error_message; | |
| 142 VERIFY1(SUCCEEDED(formatter.LoadString(IDS_UNKNOWN_APPLICATION, | |
| 143 &error_message))); | |
| 144 Error(app, ErrorContext(hr), error_message); | |
| 145 } | |
| 146 | |
| 147 const TCHAR* action = app->is_update() ? _T("update") : _T("install"); | |
| 148 app->LogTextAppendFormat(_T("Status=%s"), action); | |
| 149 | |
| 150 // Record the update available response regardless of how it is handled. | |
| 151 AppManager::Instance()->PersistSuccessfulUpdateCheckResponse(*app, true); | |
| 152 | |
| 153 if (app->is_update()) { | |
| 154 if (::IsEqualGUID(kGoopdateGuid, app->app_guid())) { | |
| 155 ++metric_worker_self_updates_available; | |
| 156 } else { | |
| 157 ++metric_worker_app_updates_available; | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 ChangeState(app, new AppStateUpdateAvailable); | |
| 162 } | |
| 163 | |
| 164 void AppStateCheckingForUpdate::HandleUpdateDeferred(App* app, | |
| 165 HRESULT code, | |
| 166 const CString& message) { | |
| 167 CORE_LOG(L3, (_T("[HandleUpdateDeferred][0x%p]"), app)); | |
| 168 | |
| 169 ASSERT1(app); | |
| 170 ASSERT1(code == GOOPDATE_E_UPDATE_DEFERRED); | |
| 171 | |
| 172 ASSERT1(app->is_update()); | |
| 173 | |
| 174 app->SetNoUpdate(ErrorContext(code), message); | |
| 175 ChangeState(app, new AppStateNoUpdate); | |
| 176 } | |
| 177 | |
| 178 void AppStateCheckingForUpdate::HandleNoUpdate(App* app, | |
| 179 HRESULT code, | |
| 180 const CString& message) { | |
| 181 CORE_LOG(L3, (_T("[HandleNoUpdate][0x%p]"), app)); | |
| 182 ASSERT1(app); | |
| 183 ASSERT1(code == GOOPDATE_E_NO_UPDATE_RESPONSE); | |
| 184 | |
| 185 app->LogTextAppendFormat(_T("Status=no-update")); | |
| 186 | |
| 187 // For installs, no update is handled as an error. | |
| 188 if (!app->is_update()) { | |
| 189 Error(app, ErrorContext(code), message); | |
| 190 return; | |
| 191 } | |
| 192 | |
| 193 VERIFY1(SUCCEEDED(update_response_utils::BuildApp(update_response_, | |
| 194 code, | |
| 195 app))); | |
| 196 AppManager::Instance()->PersistSuccessfulUpdateCheckResponse(*app, false); | |
| 197 | |
| 198 app->SetNoUpdate(ErrorContext(S_OK), message); | |
| 199 ChangeState(app, new AppStateNoUpdate); | |
| 200 } | |
| 201 | |
| 202 void AppStateCheckingForUpdate::HandleErrorResponse(App* app, | |
| 203 HRESULT code, | |
| 204 const CString& message) { | |
| 205 CORE_LOG(L3, (_T("[HandleErrorResponse][0x%p]"), app)); | |
| 206 | |
| 207 ASSERT1(app); | |
| 208 ASSERT1(FAILED(code)); | |
| 209 | |
| 210 CString log_status; | |
| 211 switch (code) { | |
| 212 case GOOPDATE_E_NO_SERVER_RESPONSE: | |
| 213 log_status = _T("no-response-received"); | |
| 214 break; | |
| 215 case GOOPDATE_E_RESTRICTED_SERVER_RESPONSE: | |
| 216 log_status = _T("restricted"); | |
| 217 break; | |
| 218 case GOOPDATE_E_UNKNOWN_APP_SERVER_RESPONSE: | |
| 219 case GOOPDATE_E_OS_NOT_SUPPORTED: | |
| 220 case GOOPDATE_E_INTERNAL_ERROR_SERVER_RESPONSE: | |
| 221 case GOOPDATE_E_SERVER_RESPONSE_NO_HASH: | |
| 222 case GOOPDATE_E_SERVER_RESPONSE_UNSUPPORTED_PROTOCOL: | |
| 223 case GOOPDATE_E_UNKNOWN_SERVER_RESPONSE: | |
| 224 default: | |
| 225 log_status = _T("error"); | |
| 226 break; | |
| 227 } | |
| 228 | |
| 229 app->LogTextAppendFormat(_T("Status=%s, Code=0x%08x"), log_status, code); | |
| 230 | |
| 231 Error(app, ErrorContext(code), message); | |
| 232 } | |
| 233 | |
| 234 void AppStateCheckingForUpdate::PersistUpdateCheckSuccessfullySent( | |
| 235 const App& app) { | |
| 236 AppManager& app_manager = *AppManager::Instance(); | |
| 237 VERIFY1(SUCCEEDED(app_manager.PersistUpdateCheckSuccessfullySent( | |
| 238 app, update_response_->GetElapsedSecondsSinceDayStart()))); | |
| 239 | |
| 240 // Here we assume that some of the members in app object | |
| 241 // (days_since_last_active_ping_, days_since_last_roll_call_, iid_, did_run_) | |
| 242 // will not be used after the update check so there is no need to update them. | |
| 243 } | |
| 244 | |
| 245 } // namespace fsm | |
| 246 | |
| 247 } // namespace omaha | |
| OLD | NEW |