2424import com .couchbase .lite .auth .Authenticator ;
2525import com .couchbase .lite .auth .Authorizer ;
2626import com .couchbase .lite .auth .LoginAuthorizer ;
27+ import com .couchbase .lite .auth .OpenIDConnectAuthorizer ;
2728import com .couchbase .lite .auth .SessionCookieAuthorizer ;
2829import com .couchbase .lite .internal .InterfaceAudience ;
2930import com .couchbase .lite .internal .RevisionInternal ;
@@ -84,6 +85,13 @@ abstract class ReplicationInternal implements BlockingQueueListener {
8485 private static int lastSessionID = 0 ;
8586 public static int RETRY_DELAY_SECONDS = 60 ; // #define kRetryDelay 60.0 in CBL_Replicator.m
8687
88+ private static ReplicationStateTransition TRANS_RUNNING_TO_IDLE =
89+ new ReplicationStateTransition (ReplicationState .RUNNING ,
90+ ReplicationState .IDLE , ReplicationTrigger .WAITING_FOR_CHANGES );
91+ private static ReplicationStateTransition TRANS_IDLE_TO_RUNNING =
92+ new ReplicationStateTransition (ReplicationState .IDLE ,
93+ ReplicationState .RUNNING , ReplicationTrigger .RESUME );
94+
8795 // Change listeners can be called back synchronously or asynchronously.
8896 protected enum ChangeListenerNotifyStyle {
8997 SYNC , ASYNC
@@ -95,6 +103,7 @@ protected enum ChangeListenerNotifyStyle {
95103 protected HttpClientFactory clientFactory ;
96104 protected String lastSequence ;
97105 protected Authenticator authenticator ;
106+ protected boolean authenticating = false ;
98107 protected String filterName ;
99108 protected Map <String , Object > filterParams ;
100109 protected List <String > documentIDs ;
@@ -148,6 +157,7 @@ protected enum ChangeListenerNotifyStyle {
148157 this .clientFactory = clientFactory ;
149158 this .lifecycle = lifecycle ;
150159 this .requestHeaders = new HashMap <String , Object >();
160+ this .authenticating = false ;
151161
152162 // The reason that notifications are ASYNC is to make the public API call
153163 // Replication.getStatus() work as expected. Because if this is set to SYNC,
@@ -252,6 +262,7 @@ protected void start() {
252262 }
253263 db .addReplication (parentReplication );
254264 db .addActiveReplication (parentReplication );
265+ this .authenticating = false ;
255266 initSessionId ();
256267 // initialize batcher
257268 initBatcher ();
@@ -298,6 +309,8 @@ protected void goOnline() {
298309 * Close all resources associated with this replicator.
299310 */
300311 protected void close () {
312+ this .authenticating = false ;
313+
301314 // cancel pending futures
302315 for (Future future : pendingFutures ) {
303316 future .cancel (false );
@@ -426,6 +439,7 @@ protected void checkSession() {
426439
427440 @ InterfaceAudience .Private
428441 protected void checkSessionAtPath (final String sessionPath ) {
442+ // First check whether a session exists
429443 Future future = sendAsyncRequest ("GET" , sessionPath , null , new RemoteRequestCompletion () {
430444
431445 @ Override
@@ -470,6 +484,8 @@ public void onCompletion(Response _response, Object result, Throwable err) {
470484
471485 @ InterfaceAudience .Private
472486 protected void login () {
487+ authenticating = true ;
488+
473489 final LoginAuthorizer loginAuth ;
474490 List <Object > login = null ;
475491 loginAuth = getAuthenticator () instanceof LoginAuthorizer ? (LoginAuthorizer ) getAuthenticator () : null ;
@@ -520,6 +536,8 @@ public void run(Database database) {
520536 }
521537
522538 private void loginFinishedWithError (Throwable error ) {
539+ authenticating = false ;
540+
523541 if (error != null ) {
524542 Log .v (TAG , "%s: Login error: %s" , this , error .getMessage ());
525543 setError (error );
@@ -1183,6 +1201,7 @@ public boolean canSendCompressedRequests() {
11831201 * Actual work of stopping the replication process.
11841202 */
11851203 protected void stop () {
1204+ this .authenticating = false ;
11861205 // clear batcher
11871206 batcher .clear ();
11881207 // set non-continuous
@@ -1452,9 +1471,19 @@ private void logTransition(Transition<ReplicationState, ReplicationTrigger> tran
14521471 transition .getSource (), transition .getDestination (), transition .getTrigger (), this );
14531472 }
14541473
1455- private void notifyChangeListenersStateTransition (Transition <ReplicationState , ReplicationTrigger > transition ) {
1474+ private void notifyChangeListenersStateTransition (
1475+ Transition <ReplicationState , ReplicationTrigger > transition ) {
14561476 logTransition (transition );
1457- Replication .ChangeEvent changeEvent = new Replication .ChangeEvent (this , new ReplicationStateTransition (transition ));
1477+
1478+ ReplicationStateTransition replStateTrans = new ReplicationStateTransition (transition );
1479+
1480+ if ((TRANS_RUNNING_TO_IDLE .equals (replStateTrans )
1481+ || TRANS_IDLE_TO_RUNNING .equals (replStateTrans )) && authenticating ) {
1482+ Log .i (TAG , "During middle of authentication, not notify Replicator state change" );
1483+ return ;
1484+ }
1485+
1486+ Replication .ChangeEvent changeEvent = new Replication .ChangeEvent (this , replStateTrans );
14581487 notifyChangeListeners (changeEvent );
14591488 }
14601489
0 commit comments