diff --git a/Sensus.Shared/Authentication/AuthenticationService.cs b/Sensus.Shared/Authentication/AuthenticationService.cs index 4a5f48ec7..546207df4 100644 --- a/Sensus.Shared/Authentication/AuthenticationService.cs +++ b/Sensus.Shared/Authentication/AuthenticationService.cs @@ -266,8 +266,9 @@ public async Task EnvelopeAsync(byte[] unencryptedBytes, int symmetricKeySizeBit } catch (WebException ex) { - // don't report the exception if it was caused by a connection failure, as we'll get this under expected conditions. - if (ex.Status == WebExceptionStatus.ConnectFailure) + // don't report the exceptions caused by connection issues, as we'll get these under normal operating conditions (e.g., lack of wifi). + if (ex.Status == WebExceptionStatus.ConnectFailure || + ex.Status == WebExceptionStatus.NameResolutionFailure) { SensusServiceHelper.Get().Logger.Log("Failed to connect when running KMS-based envelope encryption: " + ex.Message, LoggingLevel.Normal, GetType()); } @@ -277,13 +278,23 @@ public async Task EnvelopeAsync(byte[] unencryptedBytes, int symmetricKeySizeBit SensusException.Report("Non-connection web exception when running KMS-based envelope encryption: " + ex.Message, ex); } - // always throw the exception though, as we did not succeed. + // always throw the exception, as we did not succeed. + throw ex; + } + // do not report cancellation exceptions, as we'll get these under normal operating conditions (timeouts, delays, etc.) + catch (OperationCanceledException ex) + { + SensusServiceHelper.Get().Logger.Log("Cancelled KMS-based envelope encryption: " + ex.Message, LoggingLevel.Normal, GetType()); + + // always throw the exception, as we did not succeed. throw ex; } // any other exceptions may be problematic, so report and throw them. catch (Exception ex) { SensusException.Report("Exception when running KMS-based envelope encryption: " + ex.Message, ex); + + // always throw the exception, as we did not succeed. throw ex; } } diff --git a/Sensus.Shared/Notifications/Notifier.cs b/Sensus.Shared/Notifications/Notifier.cs index f4cfb4480..7d8d2007a 100644 --- a/Sensus.Shared/Notifications/Notifier.cs +++ b/Sensus.Shared/Notifications/Notifier.cs @@ -168,7 +168,8 @@ public async Task ProcessReceivedPushNotificationAsync(string protocolId, string } catch (Exception ex) { - SensusException.Report("Failed to get protocol with id " + protocolId + ": " + ex.Message, ex); + // it's possible for the user to delete the protocol but to continue receiving push notifications. ignore them. + SensusServiceHelper.Get().Logger.Log("Failed to get protocol " + protocolId + " for push notification: " + ex.Message, LoggingLevel.Normal, GetType()); return; } diff --git a/Sensus.Shared/SensusServiceHelper.cs b/Sensus.Shared/SensusServiceHelper.cs index 20b8cbec0..2fd025aa5 100644 --- a/Sensus.Shared/SensusServiceHelper.cs +++ b/Sensus.Shared/SensusServiceHelper.cs @@ -682,6 +682,12 @@ public async Task AddRunningProtocolIdAsync(string id) // get fresh credentials and check the protocol ID AmazonS3Credentials testCredentials = await protocolToTest.AuthenticationService.GetCredentialsAsync(); + // we're getting app center errors indicating a null reference somewhere in this try clause. do some extra reporting. + if (testCredentials == null) + { + throw new NullReferenceException("Returned test credentials are null."); + } + if (protocolToTest.Id != testCredentials.ProtocolId) { // we're about to stop and delete the current protocol. don't bother testing it once we're done. @@ -692,8 +698,16 @@ public async Task AddRunningProtocolIdAsync(string id) await protocolToTest.StopAsync(); await protocolToTest.DeleteAsync(); - // get the desired protocol and wire it up with the current authentication service + // get the desired protocol Protocol desiredProtocol = await Protocol.DeserializeAsync(new Uri(testCredentials.ProtocolURL), testCredentials); + + // we're getting app center errors indicating a null reference somewhere in this try clause. do some extra reporting. + if (desiredProtocol == null) + { + throw new NullReferenceException("Retrieved new protcol that was null."); + } + + // wire up new protocol with the current authentication service desiredProtocol.ParticipantId = protocolToTest.AuthenticationService.Account.ParticipantId; desiredProtocol.AuthenticationService = protocolToTest.AuthenticationService; desiredProtocol.AuthenticationService.Protocol = desiredProtocol; @@ -704,7 +718,7 @@ public async Task AddRunningProtocolIdAsync(string id) // gained in doing so. rather, just report the exception and continue running the new protocol. if (desiredProtocol.Id != testCredentials.ProtocolId) { - SensusException.Report("Retrieved new protocol on the fly, but its identifier does not match that of the credentials."); + SensusException.Report("Retrieved new protocol, but its identifier does not match that of the credentials."); } } } diff --git a/Sensus.Shared/UI/ProtocolPage.cs b/Sensus.Shared/UI/ProtocolPage.cs index b5a0ef580..9f19505aa 100644 --- a/Sensus.Shared/UI/ProtocolPage.cs +++ b/Sensus.Shared/UI/ProtocolPage.cs @@ -79,32 +79,45 @@ public ProtocolPage(Protocol protocol) setIdButton.Clicked += async (o, e) => { - Input input = await SensusServiceHelper.Get().PromptForInputAsync("Set Study Identifier", new SingleLineTextInput("Identifier:", "id", Keyboard.Text) + if (await DisplayAlert("Confirm", "Setting the study identifier should not be necessary. Proceed only if you understand the consequences. Do you wish to proceed?", "Yes", "No")) { - Required = true + string newId = null; - }, CancellationToken.None, true, "Set", null, null, "Are you sure you wish to set the study identifier? This should not be necessary under normal circumstances. Proceed only if you understand the implications.", false); + if (await DisplayAlert("Random Identifier", "Do you wish to use a random identifier?", "Yes", "No")) + { + newId = Guid.NewGuid().ToString(); + } + else + { + Input input = await SensusServiceHelper.Get().PromptForInputAsync("Study Identifier", new SingleLineTextInput("Identifier:", "id", Keyboard.Text) + { + Required = true - if (string.IsNullOrWhiteSpace(input?.Value?.ToString())) - { - await SensusServiceHelper.Get().FlashNotificationAsync("Identifier not set."); - return; - } + }, CancellationToken.None, true, "Set", null, null, null, false); - string newId = input.Value.ToString().Trim(); + newId = input?.Value?.ToString().Trim(); + } - if (protocol.Id == newId) - { - await SensusServiceHelper.Get().FlashNotificationAsync("Identifier unchanged."); - } - else if (SensusServiceHelper.Get().RegisteredProtocols.Any(p => p.Id == newId)) - { - await SensusServiceHelper.Get().FlashNotificationAsync("A study with the same identifier already exists."); - } - else - { - protocol.Id = newId; - await SensusServiceHelper.Get().FlashNotificationAsync("Identifier set."); + if (string.IsNullOrWhiteSpace(newId)) + { + await SensusServiceHelper.Get().FlashNotificationAsync("No identifier supplied. Identifier not set."); + } + else + { + if (protocol.Id == newId) + { + await SensusServiceHelper.Get().FlashNotificationAsync("Identifier unchanged."); + } + else if (SensusServiceHelper.Get().RegisteredProtocols.Any(p => p.Id == newId)) + { + await SensusServiceHelper.Get().FlashNotificationAsync("A study with the same identifier already exists. Identifier not set."); + } + else + { + protocol.Id = newId; + await SensusServiceHelper.Get().FlashNotificationAsync("Identifier set."); + } + } } };