@@ -120,6 +120,11 @@ class ApproovException implements Exception {
120120 ApproovException (String cause) {
121121 this .cause = cause;
122122 }
123+
124+ @override
125+ String toString () {
126+ return "ApproovException: $cause " ;
127+ }
123128}
124129
125130/// ApproovNetworkException indicates an exception caused by networking conditions which is likely to be
@@ -129,6 +134,11 @@ class ApproovNetworkException extends ApproovException {
129134 ///
130135 /// @param cause is a message giving the cause of the exception
131136 ApproovNetworkException (String cause) : super (cause) {}
137+
138+ @override
139+ String toString () {
140+ return "ApproovNetworkException: $cause " ;
141+ }
132142}
133143
134144/// ApproovRejectionException provides additional information if the app has been rejected by Approov.
@@ -148,6 +158,11 @@ class ApproovRejectionException extends ApproovException {
148158 this .arc = arc;
149159 this .rejectionReasons = rejectionReasons;
150160 }
161+
162+ @override
163+ String toString () {
164+ return "ApproovRejectionException: $cause ARC:$arc reasons:$rejectionReasons " ;
165+ }
151166}
152167
153168// ApproovService is a singleton for managing the underlying Approov SDK itself. It provides a number of user accessible
@@ -1135,8 +1150,7 @@ class ApproovService {
11351150 /// require another probe.
11361151 ///
11371152 /// @param url for where to retrieve the certificates with a GET request
1138- /// @return a list of certificates (each as a Uint8list) for the host specified in the URL, null if an error occurred,
1139- /// or an empty list if no suitable certificates are available.
1153+ /// @return a list of certificates (each as a Uint8list) for the host specified in the URL or null if an error occurred
11401154 static Future <List <Uint8List >?> _fetchHostCertificates (Uri url) async {
11411155 List <Uint8List >? hostCertificates = _hostCertificates[url.host];
11421156 if (hostCertificates == null ) {
@@ -1177,17 +1191,32 @@ class ApproovService {
11771191 _platformTransactions.remove (transactionID);
11781192 }
11791193
1180- // wait on the transaction to complete
1194+ // wait on the transaction to complete and process the results
11811195 final results = await completer.future;
11821196 if (results is Map <Object ?, Object ?>) {
1183- List fetchedHostCertificates = results["Certificates" ] as List <dynamic >;
1184- hostCertificates = [];
1185- for (final cert in fetchedHostCertificates) {
1186- hostCertificates.add (cert as Uint8List );
1197+ if (results.containsKey ("Certificates" )) {
1198+ // certificate were fetched so we cache them
1199+ List fetchedHostCertificates = results["Certificates" ] as List <dynamic >;
1200+ hostCertificates = [];
1201+ for (final cert in fetchedHostCertificates) {
1202+ hostCertificates.add (cert as Uint8List );
1203+ }
1204+ _hostCertificates[url.host] = hostCertificates;
1205+ Log .d ("$TAG : $isolate fetchHostCertificates ${url .host } obtained ${hostCertificates .length } certificates" );
1206+ } else if (results.containsKey ("Error" )) {
1207+ // there was a specific error fetching the certificates
1208+ String error = results["Error" ] as String ;
1209+ Log .d ("$TAG : $isolate fetchHostCertificates ${url .host }: $error " );
1210+ return null ;
1211+ } else {
1212+ // there was an unknown error fetching the certificates
1213+ Log .d ("$TAG : $isolate fetchHostCertificates ${url .host } error" );
1214+ return null ;
11871215 }
1188-
1189- // cache the obtained host certificates
1190- _hostCertificates[url.host] = hostCertificates;
1216+ } else {
1217+ // there was an unknown return format fetching the certificates
1218+ Log .d ("$TAG : $isolate fetchHostCertificates ${url .host } bad response" );
1219+ return null ;
11911220 }
11921221 } catch (err) {
11931222 throw ApproovException ('$err ' );
@@ -1557,7 +1586,7 @@ class _ApproovHttpClientRequest implements HttpClientRequest {
15571586/// Dart IO library's HttpClient.
15581587class ApproovHttpClient implements HttpClient {
15591588 // logging tag
1560- static const String TAG = "ApproovHttpClient" ;
1589+ static const String TAG = "ApproovService: ApproovHttpClient" ;
15611590
15621591 // internal HttpClient delegate, will be rebuilt if pinning fails (or pins change). It is not set to a pinned
15631592 // HttpClient initially, but this is just used to hold any state updates that might occur before a connection
@@ -1572,7 +1601,7 @@ class ApproovHttpClient implements HttpClient {
15721601 // re-create the delegate pinned HttpClient.
15731602 String ? _connectedHost;
15741603
1575- // indicates whether the ApproovHttpClient has been closed by calling close().
1604+ // indicates whether the ApproovHttpClient has been closed by calling close()
15761605 bool _isClosed = false ;
15771606
15781607 // state required to implement getters and setters required by the HttpClient interface
@@ -1594,17 +1623,20 @@ class ApproovHttpClient implements HttpClient {
15941623 /// @param cert is the certificate which could not be authenticated
15951624 /// @param host is the host name of the server to which the request is being sent
15961625 /// @param port is the port of the server
1626+ /// @return false to prevent the request from being sent
15971627 bool _pinningFailureCallback (X509Certificate cert, String host, int port) {
1628+ // reset host certificates and delegate pinned HttpClient connected host to force them to be recreated
1629+ Log .d ("$TAG : pinning failure callback for $host " );
1630+ ApproovService ._removeCertificates (host);
1631+ _connectedHost = null ;
1632+
1633+ // call any user defined function for its side effects only (as we are going to reject anyway)
15981634 Function (X509Certificate cert, String host, int port)? badCertificateCallback = _badCertificateCallback;
15991635 if (badCertificateCallback != null ) {
1600- // call the user defined function for its side effects only (as we are going to reject anyway)
16011636 badCertificateCallback (cert, host, port);
16021637 }
16031638
1604- // reset host certificates and delegate pinned HttpClient connected host to force them to be recreated
1605- Log .d ("$TAG : Pinning failure callback for $host " );
1606- ApproovService ._removeCertificates (host);
1607- _connectedHost = null ;
1639+ // prevent the request from being sent
16081640 return false ;
16091641 }
16101642
@@ -1637,7 +1669,7 @@ class ApproovHttpClient implements HttpClient {
16371669 Map <dynamic , dynamic > allPins = {};
16381670 String isolate = ApproovService ._isRootIsolate ? "root" : "background" ;
16391671 if (isExcluded) {
1640- // get whatever pins we currrently have without forcing a fetch of new ones
1672+ // get whatever pins we currently have without forcing a fetch of new ones
16411673 allPins = await ApproovService ._getPins ("public-key-sha256" );
16421674 } else {
16431675 // start the process of fetching an Approov token to get the latest configuration
@@ -1655,6 +1687,7 @@ class ApproovHttpClient implements HttpClient {
16551687 if (fetchResult.isConfigChanged) {
16561688 await ApproovService ._fetchConfig ();
16571689 ApproovService ._removeAllCertificates ();
1690+ Log .d ("$TAG : $isolate configuration change" );
16581691 }
16591692
16601693 // get pins from Approov - note that it is still possible at this point if the token fetch failed that no pins
@@ -1771,6 +1804,8 @@ class ApproovHttpClient implements HttpClient {
17711804 // if we have an active connection to a different host we need to tear down the delegate
17721805 // pinned HttpClient and create a new one with the correct pinning
17731806 if (_connectedHost != host) {
1807+ String isolate = ApproovService ._isRootIsolate ? "root" : "background" ;
1808+ Log .d ("$TAG : $isolate open pinned delegate creation for $host :$port " );
17741809 Uri url = Uri (scheme: "https" , host: host, port: port, path: path);
17751810 Future <HttpClient > futureDelegatePinnedHttpClient = _createPinnedHttpClient (url);
17761811 _futureDelegatePinnedHttpClient = futureDelegatePinnedHttpClient;
@@ -1802,6 +1837,8 @@ class ApproovHttpClient implements HttpClient {
18021837 // if we have an active connection to a different host we need to tear down the delegate
18031838 // pinned HttpClient and create a new one with the correct pinning
18041839 if (_connectedHost != url.host) {
1840+ String isolate = ApproovService ._isRootIsolate ? "root" : "background" ;
1841+ Log .d ("$TAG : $isolate openUrl pinned delegate creation for $url .host:$url .port" );
18051842 Future <HttpClient > futureDelegatePinnedHttpClient = _createPinnedHttpClient (url);
18061843 _futureDelegatePinnedHttpClient = futureDelegatePinnedHttpClient;
18071844 HttpClient httpClient = await futureDelegatePinnedHttpClient;
@@ -1937,7 +1974,7 @@ class ApproovHttpClient implements HttpClient {
19371974// and adds the desired behavior.
19381975class ApproovClient extends http.BaseClient {
19391976 // logging tag
1940- static const String TAG = "ApproovClient" ;
1977+ static const String TAG = "ApproovService: ApproovClient" ;
19411978
19421979 // internal client delegate used to perform the actual requests
19431980 http.Client ? _delegateClient;
0 commit comments