author | Nick Alexander <nalexander@mozilla.com> |
Thu, 31 May 2012 12:21:08 -0700 | |
changeset 95385 | 5e22cc18646d49b94b7d1add0f440f98f4f2d982 |
parent 95384 | 0a4417ac4889c92ca712d02f4e9f02f77df140fb |
child 95387 | c4c66d11293524e1a4463fbb6f65fa056bca858f |
push id | 10097 |
push user | nalexander@mozilla.com |
push date | Thu, 31 May 2012 20:52:28 +0000 |
treeherder | mozilla-inbound@5e22cc18646d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | rnewman |
bugs | 736393 |
milestone | 15.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/mobile/android/base/android-sync-files.mk +++ b/mobile/android/base/android-sync-files.mk @@ -1,14 +1,14 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # These files are managed in the android-sync repo. Do not modify directly, or your changes will be lost. -SYNC_JAVA_FILES := sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CommandProcessor.java sync/CommandRunner.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/crypto/PersistedCrypto5Keys.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/ClientsDataDelegate.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/EngineSettings.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeJson.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/stage/CompleteStage.java sync/jpake/stage/ComputeFinalStage.java sync/jpake/stage/ComputeKeyVerificationStage.java sync/jpake/stage/ComputeStepOneStage.java sync/jpake/stage/ComputeStepTwoStage.java sync/jpake/stage/DecryptDataStage.java sync/jpake/stage/DeleteChannel.java sync/jpake/stage/GetChannelStage.java sync/jpake/stage/GetRequestStage.java sync/jpake/stage/JPakeStage.java sync/jpake/stage/PutRequestStage.java sync/jpake/stage/VerifyPairingStage.java sync/jpake/Zkp.java sync/KeyBundleProvider.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/middleware/MiddlewareRepositorySession.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/ConnectionMonitorThread.java sync/net/HandleProgressException.java sync/net/HttpResponseObserver.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/net/WBORequestDelegate.java sync/NoCollectionKeysSetException.java sync/NodeAuthenticationException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/NullClusterURLException.java sync/PersistedMetaGlobal.java sync/PrefsSource.java sync/receivers/UpgradeReceiver.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BookmarksDeletionManager.java sync/repositories/android/BookmarksInsertionManager.java sync/repositories/android/BrowserContractHelpers.java sync/repositories/android/CachedSQLiteOpenHelper.java sync/repositories/android/ClientsDatabase.java sync/repositories/android/ClientsDatabaseAccessor.java sync/repositories/android/FennecControlHelper.java sync/repositories/android/FennecTabsRepository.java sync/repositories/android/FormHistoryRepositorySession.java sync/repositories/android/PasswordsRepositorySession.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/ClientRecord.java sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/FormHistoryRecord.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.java sync/repositories/domain/VersionConstants.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoContentProviderException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/ActivityUtils.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/InvalidSyncKeyException.java sync/setup/SyncAccounts.java sync/setup/SyncAuthenticatorService.java sync/stage/AbstractNonRepositorySyncStage.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureCrypto5KeysStage.java sync/stage/FennecTabsServerSyncStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/FormHistoryServerSyncStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/PasswordsServerSyncStage.java sync/stage/ServerSyncStage.java sync/stage/SyncClientsEngineStage.java sync/stage/UploadMetaGlobalStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java +SYNC_JAVA_FILES := sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CommandProcessor.java sync/CommandRunner.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/crypto/PersistedCrypto5Keys.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/ClientsDataDelegate.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/EngineSettings.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeJson.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/stage/CompleteStage.java sync/jpake/stage/ComputeFinalStage.java sync/jpake/stage/ComputeKeyVerificationStage.java sync/jpake/stage/ComputeStepOneStage.java sync/jpake/stage/ComputeStepTwoStage.java sync/jpake/stage/DecryptDataStage.java sync/jpake/stage/DeleteChannel.java sync/jpake/stage/GetChannelStage.java sync/jpake/stage/GetRequestStage.java sync/jpake/stage/JPakeStage.java sync/jpake/stage/PutRequestStage.java sync/jpake/stage/VerifyPairingStage.java sync/jpake/Zkp.java sync/KeyBundleProvider.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/middleware/MiddlewareRepositorySession.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/ConnectionMonitorThread.java sync/net/HandleProgressException.java sync/net/HttpResponseObserver.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/net/WBORequestDelegate.java sync/NoCollectionKeysSetException.java sync/NodeAuthenticationException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/NullClusterURLException.java sync/PersistedMetaGlobal.java sync/PrefsSource.java sync/receivers/UpgradeReceiver.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BookmarksDeletionManager.java sync/repositories/android/BookmarksInsertionManager.java sync/repositories/android/BrowserContractHelpers.java sync/repositories/android/CachedSQLiteOpenHelper.java sync/repositories/android/ClientsDatabase.java sync/repositories/android/ClientsDatabaseAccessor.java sync/repositories/android/FennecControlHelper.java sync/repositories/android/FennecTabsRepository.java sync/repositories/android/FormHistoryRepositorySession.java sync/repositories/android/PasswordsRepositorySession.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/ClientRecord.java sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/FormHistoryRecord.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.java sync/repositories/domain/VersionConstants.java sync/repositories/FetchFailedException.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoContentProviderException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreFailedException.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/Server11PreviousPostFailedException.java sync/Server11RecordPostFailedException.java sync/setup/activities/AccountActivity.java sync/setup/activities/ActivityUtils.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/InvalidSyncKeyException.java sync/setup/SyncAccounts.java sync/setup/SyncAuthenticatorService.java sync/stage/AbstractNonRepositorySyncStage.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureCrypto5KeysStage.java sync/stage/FennecTabsServerSyncStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/FormHistoryServerSyncStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/PasswordsServerSyncStage.java sync/stage/ServerSyncStage.java sync/stage/SyncClientsEngineStage.java sync/stage/UploadMetaGlobalStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/ServerLocalSynchronizer.java sync/synchronizer/ServerLocalSynchronizerSession.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java SYNC_PP_JAVA_FILES := sync/GlobalConstants.java SYNC_THIRDPARTY_JAVA_FILES := httpclientandroidlib/androidextra/HttpClientAndroidLog.java httpclientandroidlib/annotation/GuardedBy.java httpclientandroidlib/annotation/Immutable.java httpclientandroidlib/annotation/NotThreadSafe.java httpclientandroidlib/annotation/ThreadSafe.java httpclientandroidlib/auth/AUTH.java httpclientandroidlib/auth/AuthenticationException.java httpclientandroidlib/auth/AuthScheme.java httpclientandroidlib/auth/AuthSchemeFactory.java httpclientandroidlib/auth/AuthSchemeRegistry.java httpclientandroidlib/auth/AuthScope.java httpclientandroidlib/auth/AuthState.java httpclientandroidlib/auth/BasicUserPrincipal.java httpclientandroidlib/auth/ContextAwareAuthScheme.java httpclientandroidlib/auth/Credentials.java httpclientandroidlib/auth/InvalidCredentialsException.java httpclientandroidlib/auth/MalformedChallengeException.java httpclientandroidlib/auth/NTCredentials.java httpclientandroidlib/auth/NTUserPrincipal.java httpclientandroidlib/auth/params/AuthParamBean.java httpclientandroidlib/auth/params/AuthParams.java httpclientandroidlib/auth/params/AuthPNames.java httpclientandroidlib/auth/UsernamePasswordCredentials.java httpclientandroidlib/client/AuthCache.java httpclientandroidlib/client/AuthenticationHandler.java httpclientandroidlib/client/CircularRedirectException.java httpclientandroidlib/client/ClientProtocolException.java httpclientandroidlib/client/CookieStore.java httpclientandroidlib/client/CredentialsProvider.java httpclientandroidlib/client/entity/DecompressingEntity.java httpclientandroidlib/client/entity/DeflateDecompressingEntity.java httpclientandroidlib/client/entity/GzipDecompressingEntity.java httpclientandroidlib/client/entity/UrlEncodedFormEntity.java httpclientandroidlib/client/HttpClient.java httpclientandroidlib/client/HttpRequestRetryHandler.java httpclientandroidlib/client/HttpResponseException.java httpclientandroidlib/client/methods/AbortableHttpRequest.java httpclientandroidlib/client/methods/HttpDelete.java httpclientandroidlib/client/methods/HttpEntityEnclosingRequestBase.java httpclientandroidlib/client/methods/HttpGet.java httpclientandroidlib/client/methods/HttpHead.java httpclientandroidlib/client/methods/HttpOptions.java httpclientandroidlib/client/methods/HttpPost.java httpclientandroidlib/client/methods/HttpPut.java httpclientandroidlib/client/methods/HttpRequestBase.java httpclientandroidlib/client/methods/HttpTrace.java httpclientandroidlib/client/methods/HttpUriRequest.java httpclientandroidlib/client/NonRepeatableRequestException.java httpclientandroidlib/client/params/AllClientPNames.java httpclientandroidlib/client/params/AuthPolicy.java httpclientandroidlib/client/params/ClientParamBean.java httpclientandroidlib/client/params/ClientPNames.java httpclientandroidlib/client/params/CookiePolicy.java httpclientandroidlib/client/params/HttpClientParams.java httpclientandroidlib/client/protocol/ClientContext.java httpclientandroidlib/client/protocol/ClientContextConfigurer.java httpclientandroidlib/client/protocol/RequestAcceptEncoding.java httpclientandroidlib/client/protocol/RequestAddCookies.java httpclientandroidlib/client/protocol/RequestAuthCache.java httpclientandroidlib/client/protocol/RequestClientConnControl.java httpclientandroidlib/client/protocol/RequestDefaultHeaders.java httpclientandroidlib/client/protocol/RequestProxyAuthentication.java httpclientandroidlib/client/protocol/RequestTargetAuthentication.java httpclientandroidlib/client/protocol/ResponseAuthCache.java httpclientandroidlib/client/protocol/ResponseContentEncoding.java httpclientandroidlib/client/protocol/ResponseProcessCookies.java httpclientandroidlib/client/RedirectException.java httpclientandroidlib/client/RedirectHandler.java httpclientandroidlib/client/RedirectStrategy.java httpclientandroidlib/client/RequestDirector.java httpclientandroidlib/client/ResponseHandler.java httpclientandroidlib/client/UserTokenHandler.java httpclientandroidlib/client/utils/CloneUtils.java httpclientandroidlib/client/utils/Idn.java httpclientandroidlib/client/utils/JdkIdn.java httpclientandroidlib/client/utils/Punycode.java httpclientandroidlib/client/utils/Rfc3492Idn.java httpclientandroidlib/client/utils/URIUtils.java httpclientandroidlib/client/utils/URLEncodedUtils.java httpclientandroidlib/conn/BasicEofSensorWatcher.java httpclientandroidlib/conn/BasicManagedEntity.java httpclientandroidlib/conn/ClientConnectionManager.java httpclientandroidlib/conn/ClientConnectionManagerFactory.java httpclientandroidlib/conn/ClientConnectionOperator.java httpclientandroidlib/conn/ClientConnectionRequest.java httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java httpclientandroidlib/conn/ConnectionPoolTimeoutException.java httpclientandroidlib/conn/ConnectionReleaseTrigger.java httpclientandroidlib/conn/ConnectTimeoutException.java httpclientandroidlib/conn/EofSensorInputStream.java httpclientandroidlib/conn/EofSensorWatcher.java httpclientandroidlib/conn/HttpHostConnectException.java httpclientandroidlib/conn/HttpRoutedConnection.java httpclientandroidlib/conn/ManagedClientConnection.java httpclientandroidlib/conn/MultihomePlainSocketFactory.java httpclientandroidlib/conn/OperatedClientConnection.java httpclientandroidlib/conn/params/ConnConnectionParamBean.java httpclientandroidlib/conn/params/ConnConnectionPNames.java httpclientandroidlib/conn/params/ConnManagerParamBean.java httpclientandroidlib/conn/params/ConnManagerParams.java httpclientandroidlib/conn/params/ConnManagerPNames.java httpclientandroidlib/conn/params/ConnPerRoute.java httpclientandroidlib/conn/params/ConnPerRouteBean.java httpclientandroidlib/conn/params/ConnRouteParamBean.java httpclientandroidlib/conn/params/ConnRouteParams.java httpclientandroidlib/conn/params/ConnRoutePNames.java httpclientandroidlib/conn/routing/BasicRouteDirector.java httpclientandroidlib/conn/routing/HttpRoute.java httpclientandroidlib/conn/routing/HttpRouteDirector.java httpclientandroidlib/conn/routing/HttpRoutePlanner.java httpclientandroidlib/conn/routing/RouteInfo.java httpclientandroidlib/conn/routing/RouteTracker.java httpclientandroidlib/conn/scheme/HostNameResolver.java httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactoryAdaptor.java httpclientandroidlib/conn/scheme/LayeredSocketFactory.java httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java httpclientandroidlib/conn/scheme/PlainSocketFactory.java httpclientandroidlib/conn/scheme/Scheme.java httpclientandroidlib/conn/scheme/SchemeRegistry.java httpclientandroidlib/conn/scheme/SchemeSocketFactory.java httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java httpclientandroidlib/conn/scheme/SocketFactory.java httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java httpclientandroidlib/conn/ssl/AbstractVerifier.java httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java httpclientandroidlib/conn/ssl/SSLSocketFactory.java httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java httpclientandroidlib/conn/ssl/TrustManagerDecorator.java httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java httpclientandroidlib/conn/ssl/TrustStrategy.java httpclientandroidlib/conn/ssl/X509HostnameVerifier.java httpclientandroidlib/conn/util/InetAddressUtils.java httpclientandroidlib/ConnectionClosedException.java httpclientandroidlib/ConnectionReuseStrategy.java httpclientandroidlib/cookie/ClientCookie.java httpclientandroidlib/cookie/Cookie.java httpclientandroidlib/cookie/CookieAttributeHandler.java httpclientandroidlib/cookie/CookieIdentityComparator.java httpclientandroidlib/cookie/CookieOrigin.java httpclientandroidlib/cookie/CookiePathComparator.java httpclientandroidlib/cookie/CookieRestrictionViolationException.java httpclientandroidlib/cookie/CookieSpec.java httpclientandroidlib/cookie/CookieSpecFactory.java httpclientandroidlib/cookie/CookieSpecRegistry.java httpclientandroidlib/cookie/MalformedCookieException.java httpclientandroidlib/cookie/params/CookieSpecParamBean.java httpclientandroidlib/cookie/params/CookieSpecPNames.java httpclientandroidlib/cookie/SetCookie.java httpclientandroidlib/cookie/SetCookie2.java httpclientandroidlib/cookie/SM.java httpclientandroidlib/entity/AbstractHttpEntity.java httpclientandroidlib/entity/BasicHttpEntity.java httpclientandroidlib/entity/BufferedHttpEntity.java httpclientandroidlib/entity/ByteArrayEntity.java httpclientandroidlib/entity/ContentLengthStrategy.java httpclientandroidlib/entity/ContentProducer.java httpclientandroidlib/entity/EntityTemplate.java httpclientandroidlib/entity/FileEntity.java httpclientandroidlib/entity/HttpEntityWrapper.java httpclientandroidlib/entity/InputStreamEntity.java httpclientandroidlib/entity/SerializableEntity.java httpclientandroidlib/entity/StringEntity.java httpclientandroidlib/FormattedHeader.java httpclientandroidlib/Header.java httpclientandroidlib/HeaderElement.java httpclientandroidlib/HeaderElementIterator.java httpclientandroidlib/HeaderIterator.java httpclientandroidlib/HttpClientConnection.java httpclientandroidlib/HttpConnection.java httpclientandroidlib/HttpConnectionMetrics.java httpclientandroidlib/HttpEntity.java httpclientandroidlib/HttpEntityEnclosingRequest.java httpclientandroidlib/HttpException.java httpclientandroidlib/HttpHeaders.java httpclientandroidlib/HttpHost.java httpclientandroidlib/HttpInetConnection.java httpclientandroidlib/HttpMessage.java httpclientandroidlib/HttpRequest.java httpclientandroidlib/HttpRequestFactory.java httpclientandroidlib/HttpRequestInterceptor.java httpclientandroidlib/HttpResponse.java httpclientandroidlib/HttpResponseFactory.java httpclientandroidlib/HttpResponseInterceptor.java httpclientandroidlib/HttpServerConnection.java httpclientandroidlib/HttpStatus.java httpclientandroidlib/HttpVersion.java httpclientandroidlib/impl/AbstractHttpClientConnection.java httpclientandroidlib/impl/AbstractHttpServerConnection.java httpclientandroidlib/impl/auth/AuthSchemeBase.java httpclientandroidlib/impl/auth/BasicScheme.java httpclientandroidlib/impl/auth/BasicSchemeFactory.java httpclientandroidlib/impl/auth/DigestScheme.java httpclientandroidlib/impl/auth/DigestSchemeFactory.java httpclientandroidlib/impl/auth/NTLMEngine.java httpclientandroidlib/impl/auth/NTLMEngineException.java httpclientandroidlib/impl/auth/NTLMEngineImpl.java httpclientandroidlib/impl/auth/NTLMScheme.java httpclientandroidlib/impl/auth/NTLMSchemeFactory.java httpclientandroidlib/impl/auth/RFC2617Scheme.java httpclientandroidlib/impl/auth/SpnegoTokenGenerator.java httpclientandroidlib/impl/auth/UnsupportedDigestAlgorithmException.java httpclientandroidlib/impl/client/AbstractAuthenticationHandler.java httpclientandroidlib/impl/client/AbstractHttpClient.java httpclientandroidlib/impl/client/BasicAuthCache.java httpclientandroidlib/impl/client/BasicCookieStore.java httpclientandroidlib/impl/client/BasicCredentialsProvider.java httpclientandroidlib/impl/client/BasicResponseHandler.java httpclientandroidlib/impl/client/ClientParamsStack.java httpclientandroidlib/impl/client/ContentEncodingHttpClient.java httpclientandroidlib/impl/client/DefaultConnectionKeepAliveStrategy.java httpclientandroidlib/impl/client/DefaultHttpClient.java httpclientandroidlib/impl/client/DefaultHttpRequestRetryHandler.java httpclientandroidlib/impl/client/DefaultProxyAuthenticationHandler.java httpclientandroidlib/impl/client/DefaultRedirectHandler.java httpclientandroidlib/impl/client/DefaultRedirectStrategy.java httpclientandroidlib/impl/client/DefaultRedirectStrategyAdaptor.java httpclientandroidlib/impl/client/DefaultRequestDirector.java httpclientandroidlib/impl/client/DefaultTargetAuthenticationHandler.java httpclientandroidlib/impl/client/DefaultUserTokenHandler.java httpclientandroidlib/impl/client/EntityEnclosingRequestWrapper.java httpclientandroidlib/impl/client/RedirectLocations.java httpclientandroidlib/impl/client/RequestWrapper.java httpclientandroidlib/impl/client/RoutedRequest.java httpclientandroidlib/impl/client/TunnelRefusedException.java httpclientandroidlib/impl/conn/AbstractClientConnAdapter.java httpclientandroidlib/impl/conn/AbstractPooledConnAdapter.java httpclientandroidlib/impl/conn/AbstractPoolEntry.java httpclientandroidlib/impl/conn/ConnectionShutdownException.java httpclientandroidlib/impl/conn/DefaultClientConnection.java httpclientandroidlib/impl/conn/DefaultClientConnectionOperator.java httpclientandroidlib/impl/conn/DefaultHttpRoutePlanner.java httpclientandroidlib/impl/conn/DefaultResponseParser.java httpclientandroidlib/impl/conn/HttpInetSocketAddress.java httpclientandroidlib/impl/conn/IdleConnectionHandler.java httpclientandroidlib/impl/conn/LoggingSessionInputBuffer.java httpclientandroidlib/impl/conn/LoggingSessionOutputBuffer.java httpclientandroidlib/impl/conn/ProxySelectorRoutePlanner.java httpclientandroidlib/impl/conn/SchemeRegistryFactory.java httpclientandroidlib/impl/conn/SingleClientConnManager.java httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java httpclientandroidlib/impl/conn/tsccm/BasicPooledConnAdapter.java httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java httpclientandroidlib/impl/conn/tsccm/RefQueueHandler.java httpclientandroidlib/impl/conn/tsccm/RefQueueWorker.java httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java httpclientandroidlib/impl/conn/tsccm/WaitingThread.java httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java httpclientandroidlib/impl/conn/Wire.java httpclientandroidlib/impl/cookie/AbstractCookieAttributeHandler.java httpclientandroidlib/impl/cookie/AbstractCookieSpec.java httpclientandroidlib/impl/cookie/BasicClientCookie.java httpclientandroidlib/impl/cookie/BasicClientCookie2.java httpclientandroidlib/impl/cookie/BasicCommentHandler.java httpclientandroidlib/impl/cookie/BasicDomainHandler.java httpclientandroidlib/impl/cookie/BasicExpiresHandler.java httpclientandroidlib/impl/cookie/BasicMaxAgeHandler.java httpclientandroidlib/impl/cookie/BasicPathHandler.java httpclientandroidlib/impl/cookie/BasicSecureHandler.java httpclientandroidlib/impl/cookie/BestMatchSpec.java httpclientandroidlib/impl/cookie/BestMatchSpecFactory.java httpclientandroidlib/impl/cookie/BrowserCompatSpec.java httpclientandroidlib/impl/cookie/BrowserCompatSpecFactory.java httpclientandroidlib/impl/cookie/CookieSpecBase.java httpclientandroidlib/impl/cookie/DateParseException.java httpclientandroidlib/impl/cookie/DateUtils.java httpclientandroidlib/impl/cookie/IgnoreSpec.java httpclientandroidlib/impl/cookie/IgnoreSpecFactory.java httpclientandroidlib/impl/cookie/NetscapeDomainHandler.java httpclientandroidlib/impl/cookie/NetscapeDraftHeaderParser.java httpclientandroidlib/impl/cookie/NetscapeDraftSpec.java httpclientandroidlib/impl/cookie/NetscapeDraftSpecFactory.java httpclientandroidlib/impl/cookie/PublicSuffixFilter.java httpclientandroidlib/impl/cookie/PublicSuffixListParser.java httpclientandroidlib/impl/cookie/RFC2109DomainHandler.java httpclientandroidlib/impl/cookie/RFC2109Spec.java httpclientandroidlib/impl/cookie/RFC2109SpecFactory.java httpclientandroidlib/impl/cookie/RFC2109VersionHandler.java httpclientandroidlib/impl/cookie/RFC2965CommentUrlAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965DiscardAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965DomainAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965PortAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965Spec.java httpclientandroidlib/impl/cookie/RFC2965SpecFactory.java httpclientandroidlib/impl/cookie/RFC2965VersionAttributeHandler.java httpclientandroidlib/impl/DefaultConnectionReuseStrategy.java httpclientandroidlib/impl/DefaultHttpClientConnection.java httpclientandroidlib/impl/DefaultHttpRequestFactory.java httpclientandroidlib/impl/DefaultHttpResponseFactory.java httpclientandroidlib/impl/DefaultHttpServerConnection.java httpclientandroidlib/impl/EnglishReasonPhraseCatalog.java httpclientandroidlib/impl/entity/EntityDeserializer.java httpclientandroidlib/impl/entity/EntitySerializer.java httpclientandroidlib/impl/entity/LaxContentLengthStrategy.java httpclientandroidlib/impl/entity/StrictContentLengthStrategy.java httpclientandroidlib/impl/HttpConnectionMetricsImpl.java httpclientandroidlib/impl/io/AbstractMessageParser.java httpclientandroidlib/impl/io/AbstractMessageWriter.java httpclientandroidlib/impl/io/AbstractSessionInputBuffer.java httpclientandroidlib/impl/io/AbstractSessionOutputBuffer.java httpclientandroidlib/impl/io/ChunkedInputStream.java httpclientandroidlib/impl/io/ChunkedOutputStream.java httpclientandroidlib/impl/io/ContentLengthInputStream.java httpclientandroidlib/impl/io/ContentLengthOutputStream.java httpclientandroidlib/impl/io/HttpRequestParser.java httpclientandroidlib/impl/io/HttpRequestWriter.java httpclientandroidlib/impl/io/HttpResponseParser.java httpclientandroidlib/impl/io/HttpResponseWriter.java httpclientandroidlib/impl/io/HttpTransportMetricsImpl.java httpclientandroidlib/impl/io/IdentityInputStream.java httpclientandroidlib/impl/io/IdentityOutputStream.java httpclientandroidlib/impl/io/SocketInputBuffer.java httpclientandroidlib/impl/io/SocketOutputBuffer.java httpclientandroidlib/impl/NoConnectionReuseStrategy.java httpclientandroidlib/impl/SocketHttpClientConnection.java httpclientandroidlib/impl/SocketHttpServerConnection.java httpclientandroidlib/io/BufferInfo.java httpclientandroidlib/io/EofSensor.java httpclientandroidlib/io/HttpMessageParser.java httpclientandroidlib/io/HttpMessageWriter.java httpclientandroidlib/io/HttpTransportMetrics.java httpclientandroidlib/io/SessionInputBuffer.java httpclientandroidlib/io/SessionOutputBuffer.java httpclientandroidlib/MalformedChunkCodingException.java httpclientandroidlib/message/AbstractHttpMessage.java httpclientandroidlib/message/BasicHeader.java httpclientandroidlib/message/BasicHeaderElement.java httpclientandroidlib/message/BasicHeaderElementIterator.java httpclientandroidlib/message/BasicHeaderIterator.java httpclientandroidlib/message/BasicHeaderValueFormatter.java httpclientandroidlib/message/BasicHeaderValueParser.java httpclientandroidlib/message/BasicHttpEntityEnclosingRequest.java httpclientandroidlib/message/BasicHttpRequest.java httpclientandroidlib/message/BasicHttpResponse.java httpclientandroidlib/message/BasicLineFormatter.java httpclientandroidlib/message/BasicLineParser.java httpclientandroidlib/message/BasicListHeaderIterator.java httpclientandroidlib/message/BasicNameValuePair.java httpclientandroidlib/message/BasicRequestLine.java httpclientandroidlib/message/BasicStatusLine.java httpclientandroidlib/message/BasicTokenIterator.java httpclientandroidlib/message/BufferedHeader.java httpclientandroidlib/message/HeaderGroup.java httpclientandroidlib/message/HeaderValueFormatter.java httpclientandroidlib/message/HeaderValueParser.java httpclientandroidlib/message/LineFormatter.java httpclientandroidlib/message/LineParser.java httpclientandroidlib/message/ParserCursor.java httpclientandroidlib/MethodNotSupportedException.java httpclientandroidlib/NameValuePair.java httpclientandroidlib/NoHttpResponseException.java httpclientandroidlib/params/AbstractHttpParams.java httpclientandroidlib/params/BasicHttpParams.java httpclientandroidlib/params/CoreConnectionPNames.java httpclientandroidlib/params/CoreProtocolPNames.java httpclientandroidlib/params/DefaultedHttpParams.java httpclientandroidlib/params/HttpAbstractParamBean.java httpclientandroidlib/params/HttpConnectionParamBean.java httpclientandroidlib/params/HttpConnectionParams.java httpclientandroidlib/params/HttpParams.java httpclientandroidlib/params/HttpProtocolParamBean.java httpclientandroidlib/params/HttpProtocolParams.java httpclientandroidlib/params/SyncBasicHttpParams.java httpclientandroidlib/ParseException.java httpclientandroidlib/protocol/BasicHttpContext.java httpclientandroidlib/protocol/BasicHttpProcessor.java httpclientandroidlib/protocol/DefaultedHttpContext.java httpclientandroidlib/protocol/ExecutionContext.java httpclientandroidlib/protocol/HTTP.java httpclientandroidlib/protocol/HttpContext.java httpclientandroidlib/protocol/HttpDateGenerator.java httpclientandroidlib/protocol/HttpExpectationVerifier.java httpclientandroidlib/protocol/HttpProcessor.java httpclientandroidlib/protocol/HttpRequestExecutor.java httpclientandroidlib/protocol/HttpRequestHandler.java httpclientandroidlib/protocol/HttpRequestHandlerRegistry.java httpclientandroidlib/protocol/HttpRequestHandlerResolver.java httpclientandroidlib/protocol/HttpRequestInterceptorList.java httpclientandroidlib/protocol/HttpResponseInterceptorList.java httpclientandroidlib/protocol/HttpService.java httpclientandroidlib/protocol/ImmutableHttpProcessor.java httpclientandroidlib/protocol/RequestConnControl.java httpclientandroidlib/protocol/RequestContent.java httpclientandroidlib/protocol/RequestDate.java httpclientandroidlib/protocol/RequestExpectContinue.java httpclientandroidlib/protocol/RequestTargetHost.java httpclientandroidlib/protocol/RequestUserAgent.java httpclientandroidlib/protocol/ResponseConnControl.java httpclientandroidlib/protocol/ResponseContent.java httpclientandroidlib/protocol/ResponseDate.java httpclientandroidlib/protocol/ResponseServer.java httpclientandroidlib/protocol/SyncBasicHttpContext.java httpclientandroidlib/protocol/UriPatternMatcher.java httpclientandroidlib/ProtocolException.java httpclientandroidlib/ProtocolVersion.java httpclientandroidlib/ReasonPhraseCatalog.java httpclientandroidlib/RequestLine.java httpclientandroidlib/StatusLine.java httpclientandroidlib/TokenIterator.java httpclientandroidlib/TruncatedChunkException.java httpclientandroidlib/UnsupportedHttpVersionException.java httpclientandroidlib/util/ByteArrayBuffer.java httpclientandroidlib/util/CharArrayBuffer.java httpclientandroidlib/util/EncodingUtils.java httpclientandroidlib/util/EntityUtils.java httpclientandroidlib/util/ExceptionUtils.java httpclientandroidlib/util/LangUtils.java httpclientandroidlib/util/VersionInfo.java json-simple/ItemList.java json-simple/JSONArray.java json-simple/JSONAware.java json-simple/JSONObject.java json-simple/JSONStreamAware.java json-simple/JSONValue.java json-simple/parser/ContainerFactory.java json-simple/parser/ContentHandler.java json-simple/parser/JSONParser.java json-simple/parser/ParseException.java json-simple/parser/Yylex.java json-simple/parser/Yytoken.java apache/commons/codec/binary/Base32.java apache/commons/codec/binary/Base32InputStream.java apache/commons/codec/binary/Base32OutputStream.java apache/commons/codec/binary/Base64.java apache/commons/codec/binary/Base64InputStream.java apache/commons/codec/binary/Base64OutputStream.java apache/commons/codec/binary/BaseNCodec.java apache/commons/codec/binary/BaseNCodecInputStream.java apache/commons/codec/binary/BaseNCodecOutputStream.java apache/commons/codec/binary/BinaryCodec.java apache/commons/codec/binary/Hex.java apache/commons/codec/binary/StringUtils.java apache/commons/codec/BinaryDecoder.java apache/commons/codec/BinaryEncoder.java apache/commons/codec/CharEncoding.java apache/commons/codec/Decoder.java apache/commons/codec/DecoderException.java apache/commons/codec/digest/DigestUtils.java apache/commons/codec/Encoder.java apache/commons/codec/EncoderException.java apache/commons/codec/language/AbstractCaverphone.java apache/commons/codec/language/Caverphone.java apache/commons/codec/language/Caverphone1.java apache/commons/codec/language/Caverphone2.java apache/commons/codec/language/ColognePhonetic.java apache/commons/codec/language/DoubleMetaphone.java apache/commons/codec/language/Metaphone.java apache/commons/codec/language/RefinedSoundex.java apache/commons/codec/language/Soundex.java apache/commons/codec/language/SoundexUtils.java apache/commons/codec/net/BCodec.java apache/commons/codec/net/QCodec.java apache/commons/codec/net/QuotedPrintableCodec.java apache/commons/codec/net/RFC1522Codec.java apache/commons/codec/net/URLCodec.java apache/commons/codec/net/Utils.java apache/commons/codec/StringDecoder.java apache/commons/codec/StringEncoder.java apache/commons/codec/StringEncoderComparator.java SYNC_RES_DRAWABLE := mobile/android/base/resources/drawable/pin_background.xml mobile/android/base/resources/drawable/sync_ic_launcher.png SYNC_RES_DRAWABLE_LDPI := mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png SYNC_RES_DRAWABLE_MDPI := mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png SYNC_RES_DRAWABLE_HDPI := mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png SYNC_RES_LAYOUT := res/layout/sync_account.xml res/layout/sync_setup.xml res/layout/sync_setup_failure.xml res/layout/sync_setup_jpake_waiting.xml res/layout/sync_setup_nointernet.xml res/layout/sync_setup_pair.xml res/layout/sync_setup_success.xml res/layout/sync_stub.xml SYNC_RES_VALUES := res/values/sync_styles.xml
new file mode 100644 --- /dev/null +++ b/mobile/android/base/sync/Server11PreviousPostFailedException.java @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.sync; + +/** + * A previous POST failed, so we won't send any more records this session. + */ +public class Server11PreviousPostFailedException extends SyncException { + private static final long serialVersionUID = -3582490631414624310L; +}
new file mode 100644 --- /dev/null +++ b/mobile/android/base/sync/Server11RecordPostFailedException.java @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.sync; + +/** + * The server rejected a record in its "failure" array. + */ +public class Server11RecordPostFailedException extends SyncException { + private static final long serialVersionUID = -8517471217486190314L; +}
--- a/mobile/android/base/sync/middleware/Crypto5MiddlewareRepositorySession.java +++ b/mobile/android/base/sync/middleware/Crypto5MiddlewareRepositorySession.java @@ -170,18 +170,18 @@ public class Crypto5MiddlewareRepository if (delegate == null) { throw new NoStoreDelegateException(); } CryptoRecord rec = record.getEnvelope(); rec.keyBundle = this.keyBundle; try { rec.encrypt(); } catch (UnsupportedEncodingException e) { - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } catch (CryptoException e) { - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } // Allow the inner session to do delegate handling. inner.store(rec); } }
new file mode 100644 --- /dev/null +++ b/mobile/android/base/sync/repositories/FetchFailedException.java @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.sync.repositories; + +import org.mozilla.gecko.sync.SyncException; + +public class FetchFailedException extends SyncException { + private static final long serialVersionUID = -7533105300182522946L; +}
--- a/mobile/android/base/sync/repositories/Server11RepositorySession.java +++ b/mobile/android/base/sync/repositories/Server11RepositorySession.java @@ -16,23 +16,26 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import org.json.simple.JSONArray; import org.mozilla.gecko.sync.CryptoRecord; import org.mozilla.gecko.sync.DelayedWorkTracker; import org.mozilla.gecko.sync.ExtendedJSONObject; import org.mozilla.gecko.sync.HTTPFailureException; import org.mozilla.gecko.sync.Logger; +import org.mozilla.gecko.sync.Server11PreviousPostFailedException; +import org.mozilla.gecko.sync.Server11RecordPostFailedException; import org.mozilla.gecko.sync.UnexpectedJSONException; import org.mozilla.gecko.sync.crypto.KeyBundle; import org.mozilla.gecko.sync.net.SyncStorageCollectionRequest; import org.mozilla.gecko.sync.net.SyncStorageRequest; import org.mozilla.gecko.sync.net.SyncStorageRequestDelegate; import org.mozilla.gecko.sync.net.SyncStorageResponse; import org.mozilla.gecko.sync.net.WBOCollectionRequestDelegate; +import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionBeginDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFetchRecordsDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionGuidsSinceDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionStoreDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionWipeDelegate; import org.mozilla.gecko.sync.repositories.domain.Record; import ch.boye.httpclientandroidlib.entity.ContentProducer; import ch.boye.httpclientandroidlib.entity.EntityTemplate; @@ -306,17 +309,35 @@ public class Server11RepositorySession e if (!isActive()) { delegate.onWipeFailed(new InactiveSessionException(null)); return; } // TODO: implement wipe. } protected Object recordsBufferMonitor = new Object(); + + /** + * Data of outbound records. + * <p> + * We buffer the data (rather than the <code>Record</code>) so that we can + * flush the buffer based on outgoing transmission size. + * <p> + * Access should be synchronized on <code>recordsBufferMonitor</code>. + */ protected ArrayList<byte[]> recordsBuffer = new ArrayList<byte[]>(); + + /** + * GUIDs of outbound records. + * <p> + * Used to fail entire outgoing uploads. + * <p> + * Access should be synchronized on <code>recordsBufferMonitor</code>. + */ + protected ArrayList<String> recordGuidsBuffer = new ArrayList<String>(); protected int byteCount = PER_BATCH_OVERHEAD; @Override public void store(Record record) throws NoStoreDelegateException { if (delegate == null) { throw new NoStoreDelegateException(); } this.enqueue(record); @@ -335,29 +356,32 @@ public class Server11RepositorySession e synchronized (recordsBufferMonitor) { if ((delta + byteCount > UPLOAD_BYTE_THRESHOLD) || (recordsBuffer.size() >= UPLOAD_ITEM_THRESHOLD)) { // POST the existing contents, then enqueue. flush(); } recordsBuffer.add(json); + recordGuidsBuffer.add(record.guid); byteCount += PER_RECORD_OVERHEAD + delta; } } // Asynchronously upload records. // Must be locked! protected void flush() { if (recordsBuffer.size() > 0) { final ArrayList<byte[]> outgoing = recordsBuffer; + final ArrayList<String> outgoingGuids = recordGuidsBuffer; RepositorySessionStoreDelegate uploadDelegate = this.delegate; - storeWorkQueue.execute(new RecordUploadRunnable(uploadDelegate, outgoing, byteCount)); + storeWorkQueue.execute(new RecordUploadRunnable(uploadDelegate, outgoing, outgoingGuids, byteCount)); recordsBuffer = new ArrayList<byte[]>(); + recordGuidsBuffer = new ArrayList<String>(); byteCount = PER_BATCH_OVERHEAD; } } @Override public void storeDone() { Logger.debug(LOG_TAG, "storeDone()."); synchronized (recordsBufferMonitor) { @@ -373,35 +397,52 @@ public class Server11RepositorySession e } } }; storeWorkQueue.execute(r); } } /** + * <code>true</code> if a record upload has failed this session. + * <p> + * This is only set in begin and possibly by <code>RecordUploadRunnable</code>. + * Since those are executed serially, we can use an unsynchronized + * volatile boolean here. + */ + protected volatile boolean recordUploadFailed; + + public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException { + recordUploadFailed = false; + super.begin(delegate); + } + + /** * Make an HTTP request, and convert HTTP request delegate callbacks into * store callbacks within the context of this RepositorySession. * * @author rnewman * */ protected class RecordUploadRunnable implements Runnable, SyncStorageRequestDelegate { public final String LOG_TAG = "RecordUploadRunnable"; private ArrayList<byte[]> outgoing; + private ArrayList<String> outgoingGuids; private long byteCount; public RecordUploadRunnable(RepositorySessionStoreDelegate storeDelegate, ArrayList<byte[]> outgoing, + ArrayList<String> outgoingGuids, long byteCount) { Logger.info(LOG_TAG, "Preparing record upload for " + outgoing.size() + " records (" + byteCount + " bytes)."); - this.outgoing = outgoing; + this.outgoing = outgoing; + this.outgoingGuids = outgoingGuids; this.byteCount = byteCount; } @Override public String credentials() { return serverRepository.credentialsSource.credentials(); } @@ -414,17 +455,17 @@ public class Server11RepositorySession e public void handleRequestSuccess(SyncStorageResponse response) { Logger.info(LOG_TAG, "POST of " + outgoing.size() + " records done."); ExtendedJSONObject body; try { body = response.jsonObjectBody(); // jsonObjectBody() throws or returns non-null. } catch (Exception e) { Logger.error(LOG_TAG, "Got exception parsing POST success body.", e); - // TODO + this.handleRequestError(e); return; } // Be defensive when logging timestamp. if (body.containsKey("modified")) { Long modified = body.getTimestamp("modified"); if (modified != null) { Logger.debug(LOG_TAG, "POST request success. Modified timestamp: " + modified.longValue()); @@ -432,50 +473,69 @@ public class Server11RepositorySession e Logger.warn(LOG_TAG, "POST success body contains malformed 'modified': " + body.toJSONString()); } } else { Logger.warn(LOG_TAG, "POST success body does not contain key 'modified': " + body.toJSONString()); } try { JSONArray success = body.getArray("success"); - ExtendedJSONObject failed = body.getObject("failed"); if ((success != null) && (success.size() > 0)) { Logger.debug(LOG_TAG, "Successful records: " + success.toString()); - // TODO: how do we notify without the whole record? + for (Object o : success) { + try { + delegate.onRecordStoreSucceeded((String) o); + } catch (ClassCastException e) { + Logger.error(LOG_TAG, "Got exception parsing POST success guid.", e); + // Not much to be done. + } + } long normalizedTimestamp = getNormalizedTimestamp(response); Logger.debug(LOG_TAG, "Passing back upload X-Weave-Timestamp: " + normalizedTimestamp); bumpUploadTimestamp(normalizedTimestamp); } + success = null; // Want to GC this ASAP. + + ExtendedJSONObject failed = body.getObject("failed"); if ((failed != null) && (failed.object.size() > 0)) { Logger.debug(LOG_TAG, "Failed records: " + failed.object.toString()); - // TODO: notify. + Exception ex = new Server11RecordPostFailedException(); + for (String guid : failed.keySet()) { + delegate.onRecordStoreFailed(ex, guid); + } } + failed = null; // Want to GC this ASAP. } catch (UnexpectedJSONException e) { Logger.error(LOG_TAG, "Got exception processing success/failed in POST success body.", e); // TODO return; } Logger.info(LOG_TAG, "POST of " + outgoing.size() + " records handled."); } @Override public void handleRequestFailure(SyncStorageResponse response) { - // TODO: ensure that delegate methods don't get called more than once. // TODO: call session.interpretHTTPFailure. this.handleRequestError(new HTTPFailureException(response)); } @Override public void handleRequestError(final Exception ex) { Logger.warn(LOG_TAG, "Got request error: " + ex, ex); - delegate.onRecordStoreFailed(ex); + + recordUploadFailed = true; + ArrayList<String> failedOutgoingGuids = outgoingGuids; + outgoingGuids = null; // Want to GC this ASAP. + for (String guid : failedOutgoingGuids) { + delegate.onRecordStoreFailed(ex, guid); + } + return; } public class ByteArraysContentProducer implements ContentProducer { ArrayList<byte[]> outgoing; public ByteArraysContentProducer(ArrayList<byte[]> arrays) { outgoing = arrays; } @@ -515,16 +575,25 @@ public class Server11RepositorySession e public ByteArraysEntity getBodyEntity() { ByteArraysEntity body = new ByteArraysEntity(outgoing, byteCount); return body; } @Override public void run() { + if (recordUploadFailed) { + Logger.info(LOG_TAG, "Previous record upload failed. Failing all records and not retrying."); + Exception ex = new Server11PreviousPostFailedException(); + for (String guid : outgoingGuids) { + delegate.onRecordStoreFailed(ex, guid); + } + return; + } + if (outgoing == null || outgoing.size() == 0) { Logger.debug(LOG_TAG, "No items: RecordUploadRunnable returning immediately."); return; } URI u = serverRepository.collectionURI(); SyncStorageRequest request = new SyncStorageRequest(u);
new file mode 100644 --- /dev/null +++ b/mobile/android/base/sync/repositories/StoreFailedException.java @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.sync.repositories; + +import org.mozilla.gecko.sync.SyncException; + +public class StoreFailedException extends SyncException { + private static final long serialVersionUID = 6080340122855859752L; +}
--- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java @@ -583,29 +583,29 @@ public class AndroidBrowserBookmarksRepo @Override public boolean insertFolder(BookmarkRecord record) { // A folder that is *not* deleted needs its androidID updated, so that // updateBookkeeping can re-parent, etc. Record toStore = prepareRecord(record); try { Uri recordURI = dbHelper.insert(toStore); if (recordURI == null) { - delegate.onRecordStoreFailed(new RuntimeException("Got null URI inserting folder with guid " + toStore.guid + ".")); + delegate.onRecordStoreFailed(new RuntimeException("Got null URI inserting folder with guid " + toStore.guid + "."), record.guid); return false; } toStore.androidID = ContentUris.parseId(recordURI); Logger.debug(LOG_TAG, "Inserted folder with guid " + toStore.guid + " as androidID " + toStore.androidID); updateBookkeeping(toStore); } catch (Exception e) { - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return false; } trackRecord(toStore); - delegate.onRecordStoreSucceeded(toStore); + delegate.onRecordStoreSucceeded(record.guid); return true; } /** * Implement method of BookmarksInsertionManager.BookmarkInserter. */ @Override public void bulkInsertNonFolders(Collection<BookmarkRecord> records) { @@ -618,34 +618,36 @@ public class AndroidBrowserBookmarksRepo } try { int stored = dataAccessor.bulkInsert(toStores); if (stored != toStores.size()) { // Something failed; most pessimistic action is to declare that all insertions failed. // TODO: perform the bulkInsert in a transaction and rollback unless all insertions succeed? for (Record failed : toStores) { - delegate.onRecordStoreFailed(new RuntimeException("Possibly failed to bulkInsert non-folder with guid " + failed.guid + ".")); + delegate.onRecordStoreFailed(new RuntimeException("Possibly failed to bulkInsert non-folder with guid " + failed.guid + "."), failed.guid); } return; } } catch (NullCursorException e) { - delegate.onRecordStoreFailed(e); // TODO: include which records failed. + for (Record failed : toStores) { + delegate.onRecordStoreFailed(e, failed.guid); + } return; } // Success For All! for (Record succeeded : toStores) { try { updateBookkeeping(succeeded); } catch (Exception e) { Logger.warn(LOG_TAG, "Got exception updating bookkeeping of non-folder with guid " + succeeded.guid + ".", e); } trackRecord(succeeded); - delegate.onRecordStoreSucceeded(succeeded); + delegate.onRecordStoreSucceeded(succeeded.guid); } } @Override public void finish(RepositorySessionFinishDelegate delegate) throws InactiveSessionException { // Allow these to be GCed. deletionManager = null; insertionManager = null;
--- a/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryRepositorySession.java @@ -209,17 +209,17 @@ public class AndroidBrowserHistoryReposi recordsBuffer = new ArrayList<HistoryRecord>(); Logger.debug(LOG_TAG, "Flushing " + outgoing.size() + " records to database."); // TODO: move bulkInsert to AndroidBrowserDataAccessor? int inserted = ((AndroidBrowserHistoryDataAccessor) dbHelper).bulkInsert(outgoing); if (inserted != outgoing.size()) { // Something failed; most pessimistic action is to declare that all insertions failed. // TODO: perform the bulkInsert in a transaction and rollback unless all insertions succeed? for (HistoryRecord failed : outgoing) { - delegate.onRecordStoreFailed(new RuntimeException("Failed to insert history item with guid " + failed.guid + ".")); + delegate.onRecordStoreFailed(new RuntimeException("Failed to insert history item with guid " + failed.guid + "."), failed.guid); } return; } // All good, everybody succeeded. for (HistoryRecord succeeded : outgoing) { try { // Does not use androidID -- just GUID -> String map. @@ -229,17 +229,17 @@ public class AndroidBrowserHistoryReposi throw new NullCursorException(e); } catch (ParentNotFoundException e) { // Should not happen. throw new NullCursorException(e); } catch (NullCursorException e) { throw e; } trackRecord(succeeded); - delegate.onRecordStoreSucceeded(succeeded); // At this point, we are really inserted. + delegate.onRecordStoreSucceeded(succeeded.guid); // At this point, we are really inserted. } } @Override public void storeDone() { storeWorkQueue.execute(new Runnable() { @Override public void run() {
--- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java @@ -379,17 +379,17 @@ public abstract class AndroidBrowserRepo // Store Runnables *must* complete synchronously. It's OK, they // run on a background thread. Runnable command = new Runnable() { @Override public void run() { if (!isActive()) { Logger.warn(LOG_TAG, "AndroidBrowserRepositorySession is inactive. Store failing."); - delegate.onRecordStoreFailed(new InactiveSessionException(null)); + delegate.onRecordStoreFailed(new InactiveSessionException(null), record.guid); return; } // Check that the record is a valid type. // Fennec only supports bookmarks and folders. All other types of records, // including livemarks and queries, are simply ignored. // See Bug 708149. This might be resolved by Fennec changing its database // schema, or by Sync storing non-applied records in its own private database. @@ -498,34 +498,34 @@ public abstract class AndroidBrowserRepo (toStore.deleted ? " with deleted record " : " with record ") + toStore.guid); Record replaced = replace(toStore, existingRecord); // Note that we don't track records here; deciding that is the job // of reconcileRecords. Logger.debug(LOG_TAG, "Calling delegate callback with guid " + replaced.guid + "(" + replaced.androidID + ")"); - delegate.onRecordStoreSucceeded(replaced); + delegate.onRecordStoreSucceeded(replaced.guid); return; } catch (MultipleRecordsForGuidException e) { Logger.error(LOG_TAG, "Multiple records returned for given guid: " + record.guid); - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } catch (NoGuidForIdException e) { Logger.error(LOG_TAG, "Store failed for " + record.guid, e); - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } catch (NullCursorException e) { Logger.error(LOG_TAG, "Store failed for " + record.guid, e); - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } catch (Exception e) { Logger.error(LOG_TAG, "Store failed for " + record.guid, e); - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } } }; storeWorkQueue.execute(command); } /** @@ -534,30 +534,30 @@ public abstract class AndroidBrowserRepo * * @param record the incoming record. This will be mostly blank, given that it's a deletion. * @param existingRecord the existing record. Use this to decide how to process the deletion. */ protected void storeRecordDeletion(final Record record, final Record existingRecord) { // TODO: we ought to mark the record as deleted rather than purging it, // in order to support syncing to multiple destinations. Bug 722607. dbHelper.purgeGuid(record.guid); - delegate.onRecordStoreSucceeded(record); + delegate.onRecordStoreSucceeded(record.guid); } protected void insert(Record record) throws NoGuidForIdException, NullCursorException, ParentNotFoundException { Record toStore = prepareRecord(record); Uri recordURI = dbHelper.insert(toStore); if (recordURI == null) { throw new NullCursorException(new RuntimeException("Got null URI inserting record with guid " + record.guid)); } toStore.androidID = ContentUris.parseId(recordURI); updateBookkeeping(toStore); trackRecord(toStore); - delegate.onRecordStoreSucceeded(toStore); + delegate.onRecordStoreSucceeded(toStore.guid); Logger.debug(LOG_TAG, "Inserted record with guid " + toStore.guid + " as androidID " + toStore.androidID); } protected Record replace(Record newRecord, Record existingRecord) throws NoGuidForIdException, NullCursorException, ParentNotFoundException { Record toStore = prepareRecord(newRecord); // newRecord should already have suitable androidID and guid.
--- a/mobile/android/base/sync/repositories/android/BookmarksDeletionManager.java +++ b/mobile/android/base/sync/repositories/android/BookmarksDeletionManager.java @@ -7,17 +7,16 @@ package org.mozilla.gecko.sync.repositor import java.util.HashSet; import java.util.Map; import java.util.Set; import org.mozilla.gecko.db.BrowserContract; import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.repositories.NullCursorException; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionStoreDelegate; -import org.mozilla.gecko.sync.repositories.domain.BookmarkRecord; /** * Queue up deletions. Process them at the end. * * Algorithm: * * * Collect GUIDs as we go. For convenience we partition these into * folders and non-folders. @@ -217,21 +216,18 @@ public class BookmarksDeletionManager { } private void invokeCallbacks(RepositorySessionStoreDelegate delegate, String[] nonFolderGUIDs) { if (delegate == null) { return; } Logger.trace(LOG_TAG, "Invoking store callback for " + nonFolderGUIDs.length + " GUIDs."); - final long now = System.currentTimeMillis(); - BookmarkRecord r = new BookmarkRecord(null, "bookmarks", now, true); for (String guid : nonFolderGUIDs) { - r.guid = guid; - delegate.onRecordStoreSucceeded(r); + delegate.onRecordStoreSucceeded(guid); } } /** * Clear state in case of redundancy (e.g., wipe). */ public void clear() { nonFolders.clear();
--- a/mobile/android/base/sync/repositories/android/FennecTabsRepository.java +++ b/mobile/android/base/sync/repositories/android/FennecTabsRepository.java @@ -135,36 +135,36 @@ public class FennecTabsRepository extend } final TabsRecord tabsRecord = (TabsRecord) record; Runnable command = new Runnable() { @Override public void run() { Logger.debug(LOG_TAG, "Storing tabs for client " + tabsRecord.guid); if (!isActive()) { - delegate.onRecordStoreFailed(new InactiveSessionException(null)); + delegate.onRecordStoreFailed(new InactiveSessionException(null), record.guid); return; } if (tabsRecord.guid == null) { - delegate.onRecordStoreFailed(new RuntimeException("Can't store record with null GUID.")); + delegate.onRecordStoreFailed(new RuntimeException("Can't store record with null GUID."), record.guid); return; } try { // This is nice and easy: we *always* store. final String[] selectionArgs = new String[] { tabsRecord.guid }; if (tabsRecord.deleted) { try { Logger.debug(LOG_TAG, "Clearing entry for client " + tabsRecord.guid); clientsProvider.delete(BrowserContract.Clients.CONTENT_URI, CLIENT_GUID_IS, selectionArgs); - delegate.onRecordStoreSucceeded(record); + delegate.onRecordStoreSucceeded(record.guid); } catch (Exception e) { - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); } return; } // If it exists, update the client record; otherwise insert. final ContentValues clientsCV = tabsRecord.getClientsContentValues(); Logger.debug(LOG_TAG, "Updating clients provider."); @@ -179,20 +179,20 @@ public class FennecTabsRepository extend // Now insert tabs. final ContentValues[] tabsArray = tabsRecord.getTabsContentValues(); Logger.debug(LOG_TAG, "Inserting " + tabsArray.length + " tabs for client " + tabsRecord.guid); tabsProvider.delete(BrowserContract.Tabs.CONTENT_URI, TABS_CLIENT_GUID_IS, selectionArgs); final int inserted = tabsProvider.bulkInsert(BrowserContract.Tabs.CONTENT_URI, tabsArray); Logger.trace(LOG_TAG, "Inserted: " + inserted); - delegate.onRecordStoreSucceeded(tabsRecord); + delegate.onRecordStoreSucceeded(record.guid); } catch (Exception e) { Logger.warn(LOG_TAG, "Error storing tabs.", e); - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); } } }; storeWorkQueue.execute(command); } @Override
--- a/mobile/android/base/sync/repositories/android/FormHistoryRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/FormHistoryRepositorySession.java @@ -445,17 +445,17 @@ public class FormHistoryRepositorySessio protected void enqueueRegularRecord(Record record) { synchronized (recordsBufferMonitor) { if (recordsBuffer.size() >= INSERT_ITEM_THRESHOLD) { // Insert the existing contents, then enqueue. try { flushInsertQueue(); } catch (Exception e) { - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } } // Store the ContentValues, rather than the record. recordsBuffer.add(contentValuesForRegularRecord(record)); } } @@ -486,17 +486,18 @@ public class FormHistoryRepositorySessio public void run() { Logger.debug(LOG_TAG, "Checking for residual form history items to insert."); try { synchronized (recordsBufferMonitor) { flushInsertQueue(); } storeDone(now()); } catch (Exception e) { - delegate.onRecordStoreFailed(e); + // XXX TODO + delegate.onRecordStoreFailed(e, null); } } }; storeWorkQueue.execute(command); } /** * Called when a regular record with locally unknown GUID has been fetched @@ -557,17 +558,17 @@ public class FormHistoryRepositorySessio } final FormHistoryRecord record = (FormHistoryRecord) rawRecord; Runnable command = new Runnable() { @Override public void run() { if (!isActive()) { Logger.warn(LOG_TAG, "FormHistoryRepositorySession is inactive. Store failing."); - delegate.onRecordStoreFailed(new InactiveSessionException(null)); + delegate.onRecordStoreFailed(new InactiveSessionException(null), record.guid); return; } // TODO: lift these into the session. // Temporary: this matches prior syncing semantics, in which only // the relationship between the local and remote record is considered. // In the future we'll track these two timestamps and use them to // determine which records have changed, and thus process incoming @@ -600,26 +601,26 @@ public class FormHistoryRepositorySessio return; } boolean locallyModified = existingRecord.lastModified > lastLocalRetrieval; if (!locallyModified) { Logger.trace(LOG_TAG, "Remote modified, local not. Deleting."); deleteExistingRecord(existingRecord); trackRecord(record); - delegate.onRecordStoreSucceeded(record); + delegate.onRecordStoreSucceeded(record.guid); return; } Logger.trace(LOG_TAG, "Both local and remote records have been modified."); if (record.lastModified > existingRecord.lastModified) { Logger.trace(LOG_TAG, "Remote is newer, and deleted. Purging local."); deleteExistingRecord(existingRecord); trackRecord(record); - delegate.onRecordStoreSucceeded(record); + delegate.onRecordStoreSucceeded(record.guid); return; } Logger.trace(LOG_TAG, "Remote is older, local is not deleted. Ignoring."); if (!locallyModified) { Logger.warn(LOG_TAG, "Inconsistency: old remote record is deleted, but local record not modified!"); // Ensure that this is tracked for upload. } @@ -633,59 +634,59 @@ public class FormHistoryRepositorySessio existingRecord = findExistingRecordByPayload(record); } if (existingRecord == null) { // The record is new. Logger.trace(LOG_TAG, "No match. Inserting."); insertNewRegularRecord(record); trackRecord(record); - delegate.onRecordStoreSucceeded(record); + delegate.onRecordStoreSucceeded(record.guid); return; } // We found a local duplicate. Logger.trace(LOG_TAG, "Incoming record " + record.guid + " dupes to local record " + existingRecord.guid); if (!RepoUtils.stringsEqual(record.guid, existingRecord.guid)) { // We found a local record that does NOT have the same GUID -- keep the server's version. Logger.trace(LOG_TAG, "Remote guid different from local guid. Storing to keep remote guid."); replaceExistingRecordWithRegularRecord(record, existingRecord); trackRecord(record); - delegate.onRecordStoreSucceeded(record); + delegate.onRecordStoreSucceeded(record.guid); return; } // We found a local record that does have the same GUID -- check modification times. boolean locallyModified = existingRecord.lastModified > lastLocalRetrieval; if (!locallyModified) { Logger.trace(LOG_TAG, "Remote modified, local not. Storing."); replaceExistingRecordWithRegularRecord(record, existingRecord); trackRecord(record); - delegate.onRecordStoreSucceeded(record); + delegate.onRecordStoreSucceeded(record.guid); return; } Logger.trace(LOG_TAG, "Both local and remote records have been modified."); if (record.lastModified > existingRecord.lastModified) { Logger.trace(LOG_TAG, "Remote is newer, and not deleted. Storing."); replaceExistingRecordWithRegularRecord(record, existingRecord); trackRecord(record); - delegate.onRecordStoreSucceeded(record); + delegate.onRecordStoreSucceeded(record.guid); return; } Logger.trace(LOG_TAG, "Remote is older, local is not deleted. Ignoring."); if (!locallyModified) { Logger.warn(LOG_TAG, "Inconsistency: old remote record is not deleted, but local record not modified!"); } return; } catch (Exception e) { Logger.error(LOG_TAG, "Store failed for " + record.guid, e); - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } } }; storeWorkQueue.execute(command); }
--- a/mobile/android/base/sync/repositories/android/PasswordsRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/PasswordsRepositorySession.java @@ -252,35 +252,35 @@ public class PasswordsRepositorySession final PasswordRecord remoteRecord = (PasswordRecord) record; final Runnable storeRunnable = new Runnable() { @Override public void run() { if (!isActive()) { Logger.warn(LOG_TAG, "RepositorySession is inactive. Store failing."); - delegate.onRecordStoreFailed(new InactiveSessionException(null)); + delegate.onRecordStoreFailed(new InactiveSessionException(null), record.guid); return; } final String guid = remoteRecord.guid; if (guid == null) { - delegate.onRecordStoreFailed(new RuntimeException("Can't store record with null GUID.")); + delegate.onRecordStoreFailed(new RuntimeException("Can't store record with null GUID."), record.guid); return; } PasswordRecord existingRecord; try { existingRecord = retrieveByGUID(guid); } catch (NullCursorException e) { // Indicates a serious problem. - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } catch (RemoteException e) { - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } long lastLocalRetrieval = 0; // lastSyncTimestamp? long lastRemoteRetrieval = 0; // TODO: adjust for clock skew. boolean remotelyModified = remoteRecord.lastModified > lastRemoteRetrieval; // Check deleted state first. @@ -325,33 +325,41 @@ public class PasswordsRepositorySession } return; } // End deletion logic. // Now we're processing a non-deleted incoming record. if (existingRecord == null) { trace("Looking up match for record " + remoteRecord.guid); - existingRecord = findExistingRecord(remoteRecord); + try { + existingRecord = findExistingRecord(remoteRecord); + } catch (RemoteException e) { + Logger.error(LOG_TAG, "Remote exception in findExistingRecord."); + delegate.onRecordStoreFailed(e, record.guid); + } catch (NullCursorException e) { + Logger.error(LOG_TAG, "Null cursor in findExistingRecord."); + delegate.onRecordStoreFailed(e, record.guid); + } } if (existingRecord == null) { // The record is new. trace("No match. Inserting."); Logger.debug(LOG_TAG, "Didn't find matching record. Inserting."); Record inserted = null; try { inserted = insert(remoteRecord); } catch (RemoteException e) { Logger.debug(LOG_TAG, "Record insert caused a RemoteException."); - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } trackRecord(inserted); - delegate.onRecordStoreSucceeded(inserted); + delegate.onRecordStoreSucceeded(inserted.guid); return; } // We found a local dupe. trace("Incoming record " + remoteRecord.guid + " dupes to local record " + existingRecord.guid); Logger.debug(LOG_TAG, "remote " + remoteRecord + " dupes to " + existingRecord); Record toStore = reconcileRecords(remoteRecord, existingRecord, lastRemoteRetrieval, lastLocalRetrieval); @@ -364,25 +372,25 @@ public class PasswordsRepositorySession Logger.debug(LOG_TAG, "Replacing " + existingRecord.guid + " with record " + toStore.guid); Logger.debug(LOG_TAG, "existing: " + existingRecord); Logger.debug(LOG_TAG, "toStore: " + toStore); Record replaced = null; try { replaced = replace(existingRecord, toStore); } catch (RemoteException e) { Logger.debug(LOG_TAG, "Record replace caused a RemoteException."); - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } // Note that we don't track records here; deciding that is the job // of reconcileRecords. Logger.debug(LOG_TAG, "Calling delegate callback with guid " + replaced.guid + "(" + replaced.androidID + ")"); - delegate.onRecordStoreSucceeded(replaced); + delegate.onRecordStoreSucceeded(record.guid); return; } }; storeWorkQueue.execute(storeRunnable); } @Override public void wipe(final RepositorySessionWipeDelegate delegate) { @@ -576,17 +584,17 @@ public class PasswordsRepositorySession private static final String WHERE_RECORD_DATA = Passwords.HOSTNAME + " = ? AND " + Passwords.HTTP_REALM + " = ? AND " + Passwords.FORM_SUBMIT_URL + " = ? AND " + Passwords.USERNAME_FIELD + " = ? AND " + Passwords.PASSWORD_FIELD + " = ?"; - private PasswordRecord findExistingRecord(PasswordRecord record) { + private PasswordRecord findExistingRecord(PasswordRecord record) throws NullCursorException, RemoteException { PasswordRecord foundRecord = null; Cursor cursor = null; // Only check the data table. // We can't encrypt username directly for query, so run a more general query and then filter. final String[] whereArgs = new String[] { record.hostname, record.httpRealm, record.formSubmitURL, @@ -605,40 +613,34 @@ public class PasswordsRepositorySession // so we run a more general query and then filter // the returned records for a matching username. Logger.trace(LOG_TAG, "Checking incoming [" + record.encryptedUsername + "] to [" + foundRecord.encryptedUsername + "]"); if (record.encryptedUsername.equals(foundRecord.encryptedUsername)) { Logger.trace(LOG_TAG, "Found matching record: " + foundRecord); return foundRecord; } } - } catch (RemoteException e) { - Logger.error(LOG_TAG, "Remote exception in findExistingRecord."); - delegate.onRecordStoreFailed(e); - } catch (NullCursorException e) { - Logger.error(LOG_TAG, "Null cursor in findExistingRecord."); - delegate.onRecordStoreFailed(e); } finally { if (cursor != null) { cursor.close(); } } Logger.debug(LOG_TAG, "No matching records, returning null."); return null; } private void storeRecordDeletion(Record record) { try { deleteGUID(record.guid); } catch (RemoteException e) { Logger.error(LOG_TAG, "RemoteException in password delete."); - delegate.onRecordStoreFailed(e); + delegate.onRecordStoreFailed(e, record.guid); return; } - delegate.onRecordStoreSucceeded(record); + delegate.onRecordStoreSucceeded(record.guid); } /** * Make a PasswordRecord from a Cursor. * @param cur * Cursor from query. * @param deleted * true if creating a deleted Record, false if otherwise.
--- a/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java +++ b/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java @@ -1,45 +1,43 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.sync.repositories.delegates; import java.util.concurrent.ExecutorService; -import org.mozilla.gecko.sync.repositories.domain.Record; - public class DeferredRepositorySessionStoreDelegate implements RepositorySessionStoreDelegate { protected final RepositorySessionStoreDelegate inner; protected final ExecutorService executor; public DeferredRepositorySessionStoreDelegate( RepositorySessionStoreDelegate inner, ExecutorService executor) { this.inner = inner; this.executor = executor; } @Override - public void onRecordStoreSucceeded(final Record record) { + public void onRecordStoreSucceeded(final String guid) { executor.execute(new Runnable() { @Override public void run() { - inner.onRecordStoreSucceeded(record); + inner.onRecordStoreSucceeded(guid); } }); } @Override - public void onRecordStoreFailed(final Exception ex) { + public void onRecordStoreFailed(final Exception ex, final String guid) { executor.execute(new Runnable() { @Override public void run() { - inner.onRecordStoreFailed(ex); + inner.onRecordStoreFailed(ex, guid); } }); } @Override public RepositorySessionStoreDelegate deferredStoreDelegate(ExecutorService newExecutor) { if (newExecutor == executor) { return this;
--- a/mobile/android/base/sync/repositories/delegates/RepositorySessionStoreDelegate.java +++ b/mobile/android/base/sync/repositories/delegates/RepositorySessionStoreDelegate.java @@ -1,26 +1,23 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.sync.repositories.delegates; import java.util.concurrent.ExecutorService; -import org.mozilla.gecko.sync.repositories.domain.Record; - /** * These methods *must* be invoked asynchronously. Use deferredStoreDelegate if you * need help doing this. * * @author rnewman * */ public interface RepositorySessionStoreDelegate { - public void onRecordStoreFailed(Exception ex); + public void onRecordStoreFailed(Exception ex, String recordGuid); - // Optionally called with an equivalent (but not necessarily identical) record - // when a store has succeeded. - public void onRecordStoreSucceeded(Record record); + // Called with a GUID when store has succeeded. + public void onRecordStoreSucceeded(String guid); public void onStoreCompleted(long storeEnd); public RepositorySessionStoreDelegate deferredStoreDelegate(ExecutorService executor); }
--- a/mobile/android/base/sync/stage/ServerSyncStage.java +++ b/mobile/android/base/sync/stage/ServerSyncStage.java @@ -32,16 +32,17 @@ import org.mozilla.gecko.sync.repositori import org.mozilla.gecko.sync.repositories.Repository; import org.mozilla.gecko.sync.repositories.RepositorySession; import org.mozilla.gecko.sync.repositories.RepositorySessionBundle; import org.mozilla.gecko.sync.repositories.Server11Repository; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionBeginDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionCreationDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFinishDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionWipeDelegate; +import org.mozilla.gecko.sync.synchronizer.ServerLocalSynchronizer; import org.mozilla.gecko.sync.synchronizer.Synchronizer; import org.mozilla.gecko.sync.synchronizer.SynchronizerDelegate; import android.content.Context; /** * Fetch from a server collection into a local repository, encrypting * and decrypting along the way. @@ -134,17 +135,17 @@ public abstract class ServerSyncStage im protected void persistConfig(SynchronizerConfiguration synchronizerConfiguration) { synchronizerConfiguration.persist(session.config.getBranch(bundlePrefix())); } public Synchronizer getConfiguredSynchronizer(GlobalSession session) throws NoCollectionKeysSetException, URISyntaxException, NonObjectJSONException, IOException, ParseException { Repository remote = wrappedServerRepo(); - Synchronizer synchronizer = new Synchronizer(); + Synchronizer synchronizer = new ServerLocalSynchronizer(); synchronizer.repositoryA = remote; synchronizer.repositoryB = this.getLocalRepository(); synchronizer.load(getConfig()); return synchronizer; } /** @@ -517,16 +518,9 @@ public abstract class ServerSyncStage im // This failure could be due to a 503 or a 401 and it could have headers. if (lastException instanceof HTTPFailureException) { session.handleHTTPError(((HTTPFailureException)lastException).response, reason); } else { session.abort(lastException, reason); } } - - @Override - public void onSynchronizeAborted(Synchronizer synchronize) { - Logger.info(LOG_TAG, "onSynchronizeAborted."); - - session.abort(null, "Synchronization was aborted."); - } }
--- a/mobile/android/base/sync/synchronizer/ConcurrentRecordConsumer.java +++ b/mobile/android/base/sync/synchronizer/ConcurrentRecordConsumer.java @@ -79,33 +79,34 @@ class ConcurrentRecordConsumer extends R private void consumerIsDone() { info("Consumer is done. Processed " + counter + ((counter == 1) ? " record." : " records.")); delegate.consumerIsDone(!allRecordsQueued); } @Override public void run() { + Record record; + while (true) { - synchronized (monitor) { - trace("run() took monitor."); - if (stopImmediately) { - debug("Stopping immediately. Clearing queue."); - delegate.getQueue().clear(); - debug("Notifying consumer."); - consumerIsDone(); - return; + // The queue is concurrent-safe. + while ((record = delegate.getQueue().poll()) != null) { + synchronized (monitor) { + trace("run() took monitor."); + if (stopImmediately) { + debug("Stopping immediately. Clearing queue."); + delegate.getQueue().clear(); + debug("Notifying consumer."); + consumerIsDone(); + return; + } + debug("run() dropped monitor."); } - debug("run() dropped monitor."); - } - // The queue is concurrent-safe. - while (!delegate.getQueue().isEmpty()) { - trace("Grabbing record..."); - Record record = delegate.getQueue().remove(); - trace("Storing record... " + delegate); + + trace("Storing record with guid " + record.guid + "."); try { delegate.store(record); } catch (Exception e) { // TODO: Bug 709371: track records that failed to apply. Log.e(LOG_TAG, "Caught error in store.", e); } trace("Done with record."); }
--- a/mobile/android/base/sync/synchronizer/RecordsChannel.java +++ b/mobile/android/base/sync/synchronizer/RecordsChannel.java @@ -1,16 +1,17 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.sync.synchronizer; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.ThreadPool; import org.mozilla.gecko.sync.repositories.InvalidSessionTransitionException; import org.mozilla.gecko.sync.repositories.NoStoreDelegateException; import org.mozilla.gecko.sync.repositories.RepositorySession; import org.mozilla.gecko.sync.repositories.delegates.DeferredRepositorySessionBeginDelegate; import org.mozilla.gecko.sync.repositories.delegates.DeferredRepositorySessionStoreDelegate; @@ -54,29 +55,32 @@ import org.mozilla.gecko.sync.repositori * queue empties, the consumer checks the storeDone flag. If it's set, and the * queue is exhausted, invoke onStoreCompleted. * * RecordsChannel exists to enforce this ordering of operations. * * @author rnewman * */ -class RecordsChannel implements +public class RecordsChannel implements RepositorySessionFetchRecordsDelegate, RepositorySessionStoreDelegate, RecordsConsumerDelegate, RepositorySessionBeginDelegate { private static final String LOG_TAG = "RecordsChannel"; public RepositorySession source; public RepositorySession sink; private RecordsChannelDelegate delegate; private long timestamp; private long fetchEnd = -1; + private final AtomicInteger numFetchFailed = new AtomicInteger(); + private final AtomicInteger numStoreFailed = new AtomicInteger(); + public RecordsChannel(RepositorySession source, RepositorySession sink, RecordsChannelDelegate delegate) { this.source = source; this.sink = sink; this.delegate = delegate; this.timestamp = source.lastSyncTimestamp; } /* @@ -97,46 +101,46 @@ class RecordsChannel implements return toProcess; } protected boolean isReady() { return source.isActive() && sink.isActive(); } /** - * Attempt to abort an outstanding fetch. Finish both sessions, and - * halt the consumer if it exists. + * Get the number of fetch failures recorded so far. + * @return number of fetch failures. */ - public void abort() { - if (source.isActive()) { - source.abort(); - } - if (sink.isActive()) { - sink.abort(); - } + public int getFetchFailureCount() { + return numFetchFailed.get(); + } - toProcess.clear(); - if (consumer == null) { - return; - } - consumer.halt(); + /** + * Get the number of store failures recorded so far. + * @return number of store failures. + */ + public int getStoreFailureCount() { + return numStoreFailed.get(); } /** * Start records flowing through the channel. */ public void flow() { if (!isReady()) { RepositorySession failed = source; if (source.isActive()) { failed = sink; } this.delegate.onFlowBeginFailed(this, new SessionNotBegunException(failed)); + return; } sink.setStoreDelegate(this); + numFetchFailed.set(0); + numStoreFailed.set(0); // Start a consumer thread. this.consumer = new ConcurrentRecordConsumer(this); ThreadPool.run(this.consumer); waitingForQueueDone = true; source.fetchSince(timestamp, this); } /** @@ -149,24 +153,24 @@ class RecordsChannel implements } @Override public void store(Record record) { try { sink.store(record); } catch (NoStoreDelegateException e) { Logger.error(LOG_TAG, "Got NoStoreDelegateException in RecordsChannel.store(). This should not occur. Aborting.", e); - delegate.onFlowStoreFailed(this, e); - this.abort(); + delegate.onFlowStoreFailed(this, e, record.guid); } } @Override public void onFetchFailed(Exception ex, Record record) { Logger.warn(LOG_TAG, "onFetchFailed. Calling for immediate stop.", ex); + numFetchFailed.incrementAndGet(); this.consumer.halt(); delegate.onFlowFetchFailed(this, ex); } @Override public void onFetchedRecord(Record record) { this.toProcess.add(record); this.consumer.doNotify(); @@ -185,24 +189,27 @@ class RecordsChannel implements public void onFetchCompleted(final long fetchEnd) { Logger.info(LOG_TAG, "onFetchCompleted. Stopping consumer once stores are done."); Logger.info(LOG_TAG, "Fetch timestamp is " + fetchEnd); this.fetchEnd = fetchEnd; this.consumer.queueFilled(); } @Override - public void onRecordStoreFailed(Exception ex) { + public void onRecordStoreFailed(Exception ex, String recordGuid) { + Logger.trace(LOG_TAG, "Failed to store record with guid " + recordGuid); + numStoreFailed.incrementAndGet(); this.consumer.stored(); - delegate.onFlowStoreFailed(this, ex); + delegate.onFlowStoreFailed(this, ex, recordGuid); // TODO: abort? } @Override - public void onRecordStoreSucceeded(Record record) { + public void onRecordStoreSucceeded(String guid) { + Logger.trace(LOG_TAG, "Stored record with guid " + guid); this.consumer.stored(); } @Override public void consumerIsDone(boolean allRecordsQueued) { Logger.trace(LOG_TAG, "Consumer is done. Are we waiting for it? " + waitingForQueueDone); if (waitingForQueueDone) { @@ -227,16 +234,17 @@ class RecordsChannel implements @Override public void onBeginSucceeded(RepositorySession session) { if (session == source) { Logger.info(LOG_TAG, "Source session began. Beginning sink session."); try { sink.begin(this); } catch (InvalidSessionTransitionException e) { onBeginFailed(e); + return; } } if (session == sink) { Logger.info(LOG_TAG, "Sink session began. Beginning flow."); this.flow(); return; }
--- a/mobile/android/base/sync/synchronizer/RecordsChannelDelegate.java +++ b/mobile/android/base/sync/synchronizer/RecordsChannelDelegate.java @@ -3,11 +3,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.sync.synchronizer; public interface RecordsChannelDelegate { public void onFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd); public void onFlowBeginFailed(RecordsChannel recordsChannel, Exception ex); public void onFlowFetchFailed(RecordsChannel recordsChannel, Exception ex); - public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex); + public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex, String recordGuid); public void onFlowFinishFailed(RecordsChannel recordsChannel, Exception ex); } \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/mobile/android/base/sync/synchronizer/ServerLocalSynchronizer.java @@ -0,0 +1,17 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.sync.synchronizer; + +/** + * A <code>SynchronizerSession</code> designed to be used between a remote + * server and a local repository. + * <p> + * See <code>ServerLocalSynchronizerSession</code> for error handling details. + */ +public class ServerLocalSynchronizer extends Synchronizer { + public SynchronizerSession getSynchronizerSession() { + return new ServerLocalSynchronizerSession(this, this); + } +}
new file mode 100644 --- /dev/null +++ b/mobile/android/base/sync/synchronizer/ServerLocalSynchronizerSession.java @@ -0,0 +1,76 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.sync.synchronizer; + +import org.mozilla.gecko.sync.Logger; +import org.mozilla.gecko.sync.repositories.FetchFailedException; +import org.mozilla.gecko.sync.repositories.StoreFailedException; + +/** + * A <code>SynchronizerSession</code> designed to be used between a remote + * server and a local repository. + * <p> + * Handles failure cases as follows (in the order they will occur during a sync): + * <ul> + * <li>Remote fetch failures abort.</li> + * <li>Local store failures are ignored.</li> + * <li>Local fetch failures abort.</li> + * <li>Remote store failures abort.</li> + * </ul> + */ +public class ServerLocalSynchronizerSession extends SynchronizerSession { + protected static final String LOG_TAG = "ServLocSynchronizerSess"; + + public ServerLocalSynchronizerSession(Synchronizer synchronizer, SynchronizerSessionDelegate delegate) { + super(synchronizer, delegate); + } + + public void onFirstFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) { + // Fetch failures always abort. + int numRemoteFetchFailed = recordsChannel.getFetchFailureCount(); + if (numRemoteFetchFailed > 0) { + final String message = "Got " + numRemoteFetchFailed + " failures fetching remote records!"; + Logger.warn(LOG_TAG, message + " Aborting session."); + delegate.onSynchronizeFailed(this, new FetchFailedException(), message); + return; + } + Logger.trace(LOG_TAG, "No failures fetching remote records."); + + // Local store failures are ignored. + int numLocalStoreFailed = recordsChannel.getStoreFailureCount(); + if (numLocalStoreFailed > 0) { + final String message = "Got " + numLocalStoreFailed + " failures storing local records!"; + Logger.warn(LOG_TAG, message + " Ignoring local store failures and continuing synchronizer session."); + } else { + Logger.trace(LOG_TAG, "No failures storing local records."); + } + + super.onFirstFlowCompleted(recordsChannel, fetchEnd, storeEnd); + } + + public void onSecondFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) { + // Fetch failures always abort. + int numLocalFetchFailed = recordsChannel.getFetchFailureCount(); + if (numLocalFetchFailed > 0) { + final String message = "Got " + numLocalFetchFailed + " failures fetching local records!"; + Logger.warn(LOG_TAG, message + " Aborting session."); + delegate.onSynchronizeFailed(this, new FetchFailedException(), message); + return; + } + Logger.trace(LOG_TAG, "No failures fetching local records."); + + // Remote store failures abort! + int numRemoteStoreFailed = recordsChannel.getStoreFailureCount(); + if (numRemoteStoreFailed > 0) { + final String message = "Got " + numRemoteStoreFailed + " failures storing remote records!"; + Logger.warn(LOG_TAG, message + " Aborting session."); + delegate.onSynchronizeFailed(this, new StoreFailedException(), message); + return; + } + Logger.trace(LOG_TAG, "No failures storing remote records."); + + super.onSecondFlowCompleted(recordsChannel, fetchEnd, storeEnd); + } +}
--- a/mobile/android/base/sync/synchronizer/Synchronizer.java +++ b/mobile/android/base/sync/synchronizer/Synchronizer.java @@ -22,95 +22,66 @@ import android.util.Log; * I always call exactly one of my delegate's `onSynchronized` or * `onSynchronizeFailed` callback methods. In addition, I call * `onSynchronizeAborted` before `onSynchronizeFailed` when I encounter a fetch, * store, or session error while synchronizing. * * After synchronizing, call `save` to get back a SynchronizerConfiguration with * updated bundle information. */ -public class Synchronizer { +public class Synchronizer implements SynchronizerSessionDelegate { + public static final String LOG_TAG = "SyncDelSDelegate"; + protected String configSyncID; // Used to pass syncID from load() back into save(). - /** - * I translate the fine-grained feedback of a SynchronizerSessionDelegate into - * the coarse-grained feedback of a SynchronizerDelegate. - */ - public class SynchronizerDelegateSessionDelegate implements - SynchronizerSessionDelegate { - - private static final String LOG_TAG = "SyncDelSDelegate"; - private SynchronizerDelegate synchronizerDelegate; - private SynchronizerSession session; + protected SynchronizerDelegate synchronizerDelegate; - public SynchronizerDelegateSessionDelegate(SynchronizerDelegate delegate) { - this.synchronizerDelegate = delegate; - } - - @Override - public void onInitialized(SynchronizerSession session) { - this.session = session; - session.synchronize(); - } - - @Override - public void onSynchronized(SynchronizerSession synchronizerSession) { - Log.d(LOG_TAG, "Got onSynchronized."); - Log.d(LOG_TAG, "Notifying SynchronizerDelegate."); - this.synchronizerDelegate.onSynchronized(synchronizerSession.getSynchronizer()); - } + @Override + public void onInitialized(SynchronizerSession session) { + session.synchronize(); + } - @Override - public void onSynchronizeSkipped(SynchronizerSession synchronizerSession) { - Log.d(LOG_TAG, "Got onSynchronizeSkipped."); - Log.d(LOG_TAG, "Notifying SynchronizerDelegate as if on success."); - this.synchronizerDelegate.onSynchronized(synchronizerSession.getSynchronizer()); - } - - @Override - public void onSynchronizeFailed(SynchronizerSession session, - Exception lastException, String reason) { - this.synchronizerDelegate.onSynchronizeFailed(session.getSynchronizer(), lastException, reason); - } - - @Override - public void onSynchronizeAborted(SynchronizerSession synchronizerSession) { - this.synchronizerDelegate.onSynchronizeAborted(session.getSynchronizer()); - } + @Override + public void onSynchronized(SynchronizerSession synchronizerSession) { + Log.d(LOG_TAG, "Got onSynchronized."); + Log.d(LOG_TAG, "Notifying SynchronizerDelegate."); + this.synchronizerDelegate.onSynchronized(synchronizerSession.getSynchronizer()); + } - @Override - public void onFetchError(Exception e) { - session.abort(); - synchronizerDelegate.onSynchronizeFailed(session.getSynchronizer(), e, "Got fetch error."); - } + @Override + public void onSynchronizeSkipped(SynchronizerSession synchronizerSession) { + Log.d(LOG_TAG, "Got onSynchronizeSkipped."); + Log.d(LOG_TAG, "Notifying SynchronizerDelegate as if on success."); + this.synchronizerDelegate.onSynchronized(synchronizerSession.getSynchronizer()); + } - @Override - public void onStoreError(Exception e) { - session.abort(); - synchronizerDelegate.onSynchronizeFailed(session.getSynchronizer(), e, "Got store error."); - } - - @Override - public void onSessionError(Exception e) { - session.abort(); - synchronizerDelegate.onSynchronizeFailed(session.getSynchronizer(), e, "Got session error."); - } + @Override + public void onSynchronizeFailed(SynchronizerSession session, + Exception lastException, String reason) { + this.synchronizerDelegate.onSynchronizeFailed(session.getSynchronizer(), lastException, reason); } public Repository repositoryA; public Repository repositoryB; public RepositorySessionBundle bundleA; public RepositorySessionBundle bundleB; /** + * Fetch a synchronizer session appropriate for this <code>Synchronizer</code> + */ + public SynchronizerSession getSynchronizerSession() { + return new SynchronizerSession(this, this); + } + + /** * Start synchronizing, calling delegate's callback methods. */ public void synchronize(Context context, SynchronizerDelegate delegate) { - SynchronizerDelegateSessionDelegate sessionDelegate = new SynchronizerDelegateSessionDelegate(delegate); - SynchronizerSession session = new SynchronizerSession(this, sessionDelegate); + this.synchronizerDelegate = delegate; + SynchronizerSession session = getSynchronizerSession(); session.init(context, bundleA, bundleB); } public SynchronizerConfiguration save() { return new SynchronizerConfiguration(configSyncID, bundleA, bundleB); } /**
--- a/mobile/android/base/sync/synchronizer/SynchronizerDelegate.java +++ b/mobile/android/base/sync/synchronizer/SynchronizerDelegate.java @@ -2,10 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.sync.synchronizer; public interface SynchronizerDelegate { public void onSynchronized(Synchronizer synchronizer); public void onSynchronizeFailed(Synchronizer synchronizer, Exception lastException, String reason); - public void onSynchronizeAborted(Synchronizer synchronize); }
--- a/mobile/android/base/sync/synchronizer/SynchronizerSession.java +++ b/mobile/android/base/sync/synchronizer/SynchronizerSession.java @@ -46,19 +46,19 @@ import android.content.Context; * `onSynchronizeFailed` callback methods if I have not seen an error. */ public class SynchronizerSession extends DeferrableRepositorySessionCreationDelegate implements RecordsChannelDelegate, RepositorySessionFinishDelegate { protected static final String LOG_TAG = "SynchronizerSession"; - private Synchronizer synchronizer; - private SynchronizerSessionDelegate delegate; - private Context context; + protected Synchronizer synchronizer; + protected SynchronizerSessionDelegate delegate; + protected Context context; /* * Computed during init. */ private RepositorySession sessionA; private RepositorySession sessionB; private RepositorySessionBundle bundleA; private RepositorySessionBundle bundleB; @@ -98,30 +98,16 @@ implements RecordsChannelDelegate, this.getSynchronizer().repositoryA.createSession(this, context); } // These are accessed by `abort` and `synchronize`, both of which are synchronized. // Guarded by `this`. protected RecordsChannel channelAToB; protected RecordsChannel channelBToA; - public synchronized void abort() { - // Guaranteed to have been begun by the time we get to run. - if (channelAToB != null) { - channelAToB.abort(); - } - - // Not guaranteed. It's possible for the second flow to begin after we've aborted. - // TODO: stop this from happening! - if (channelBToA != null) { - channelBToA.abort(); - } - this.delegate.onSynchronizeAborted(this); - } - /** * Please don't call this until you've been notified with onInitialized. */ public synchronized void synchronize() { // First thing: decide whether we should. if (!sessionA.dataAvailable() && !sessionB.dataAvailable()) { Logger.info(LOG_TAG, "Neither session reports data available. Short-circuiting sync."); @@ -137,109 +123,120 @@ implements RecordsChannelDelegate, // This is the *second* record channel to flow. // I, SynchronizerSession, am the delegate for the *second* flow. channelBToA = new RecordsChannel(this.sessionB, this.sessionA, this); // This is the delegate for the *first* flow. RecordsChannelDelegate channelAToBDelegate = new RecordsChannelDelegate() { public void onFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) { - Logger.info(LOG_TAG, "First RecordsChannel onFlowCompleted. Fetch end is " + fetchEnd + - ". Store end is " + storeEnd + ". Starting next."); - pendingATimestamp = fetchEnd; - storeEndBTimestamp = storeEnd; - flowAToBCompleted = true; - channelBToA.flow(); + session.onFirstFlowCompleted(recordsChannel, fetchEnd, storeEnd); } @Override public void onFlowBeginFailed(RecordsChannel recordsChannel, Exception ex) { - Logger.warn(LOG_TAG, "First RecordsChannel onFlowBeginFailed. Reporting session error.", ex); - session.delegate.onSessionError(ex); + Logger.warn(LOG_TAG, "First RecordsChannel onFlowBeginFailed. Logging session error.", ex); + session.delegate.onSynchronizeFailed(session, ex, "Failed to begin first flow."); } @Override public void onFlowFetchFailed(RecordsChannel recordsChannel, Exception ex) { - // TODO: clean up, tear down, abort. - Logger.warn(LOG_TAG, "First RecordsChannel onFlowFetchFailed. Reporting fetch error.", ex); - session.delegate.onFetchError(ex); + Logger.warn(LOG_TAG, "First RecordsChannel onFlowFetchFailed. Logging remote fetch error.", ex); } @Override - public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex) { - // TODO: clean up, tear down, abort. - Logger.warn(LOG_TAG, "First RecordsChannel onFlowStoreFailed. Reporting store error.", ex); - session.delegate.onStoreError(ex); + public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex, String recordGuid) { + Logger.warn(LOG_TAG, "First RecordsChannel onFlowStoreFailed. Logging local store error.", ex); } @Override public void onFlowFinishFailed(RecordsChannel recordsChannel, Exception ex) { - Logger.warn(LOG_TAG, "First RecordsChannel onFlowFinishedFailed. Reporting session error.", ex); - session.delegate.onSessionError(ex); + Logger.warn(LOG_TAG, "First RecordsChannel onFlowFinishedFailed. Logging session error.", ex); + session.delegate.onSynchronizeFailed(session, ex, "Failed to finish first flow."); } }; // This is the *first* channel to flow. channelAToB = new RecordsChannel(this.sessionA, this.sessionB, channelAToBDelegate); Logger.info(LOG_TAG, "Starting A to B flow. Channel is " + channelAToB); try { channelAToB.beginAndFlow(); } catch (InvalidSessionTransitionException e) { onFlowBeginFailed(channelAToB, e); } } - @Override - public void onFlowCompleted(RecordsChannel channel, long fetchEnd, long storeEnd) { - Logger.info(LOG_TAG, "Second RecordsChannel onFlowCompleted. Fetch end is " + fetchEnd + - ". Store end is " + storeEnd + ". Finishing."); + /** + * Called after the first flow completes. + * <p> + * By default, any fetch and store failures are ignored. + * @param recordsChannel the <code>RecordsChannel</code> (for error testing). + * @param fetchEnd timestamp when fetches completed. + * @param storeEnd timestamp when stores completed. + */ + public void onFirstFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) { + Logger.info(LOG_TAG, "First RecordsChannel onFlowCompleted."); + Logger.info(LOG_TAG, "Fetch end is " + fetchEnd + ". Store end is " + storeEnd + ". Starting next."); + pendingATimestamp = fetchEnd; + storeEndBTimestamp = storeEnd; + flowAToBCompleted = true; + channelBToA.flow(); + } + + /** + * Called after the second flow completes. + * <p> + * By default, any fetch and store failures are ignored. + * @param recordsChannel the <code>RecordsChannel</code> (for error testing). + * @param fetchEnd timestamp when fetches completed. + * @param storeEnd timestamp when stores completed. + */ + public void onSecondFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) { + Logger.info(LOG_TAG, "Second RecordsChannel onFlowCompleted."); + Logger.info(LOG_TAG, "Fetch end is " + fetchEnd + ". Store end is " + storeEnd + ". Finishing."); pendingBTimestamp = fetchEnd; storeEndATimestamp = storeEnd; flowBToACompleted = true; // Finish the two sessions. try { this.sessionA.finish(this); } catch (InactiveSessionException e) { this.onFinishFailed(e); + return; } } @Override + public void onFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) { + onSecondFlowCompleted(recordsChannel, fetchEnd, storeEnd); + } + + @Override public void onFlowBeginFailed(RecordsChannel recordsChannel, Exception ex) { - Logger.warn(LOG_TAG, "Second RecordsChannel onFlowBeginFailed. Reporting session error.", ex); - this.delegate.onSessionError(ex); + Logger.warn(LOG_TAG, "Second RecordsChannel onFlowBeginFailed. Logging session error.", ex); + this.delegate.onSynchronizeFailed(this, ex, "Failed to begin second flow."); } @Override public void onFlowFetchFailed(RecordsChannel recordsChannel, Exception ex) { - // TODO: clean up, tear down, abort. - Logger.warn(LOG_TAG, "Second RecordsChannel onFlowFetchFailed. Reporting fetch error.", ex); - this.delegate.onFetchError(ex); + Logger.warn(LOG_TAG, "Second RecordsChannel onFlowFetchFailed. Logging local fetch error.", ex); } - /** - * We ignore possible store errors, since failure to store a record is not - * necessarily a cause to abort. It might mean that the record should be - * tracked for re-downloading, or skipped, or we might abort. - * - * TODO: Bug 709371. - */ @Override - public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex) { - // TODO: clean up, tear down, abort. - Logger.warn(LOG_TAG, "Second RecordsChannel onFlowStoreFailed. Ignoring store error.", ex); + public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex, String recordGuid) { + Logger.warn(LOG_TAG, "Second RecordsChannel onFlowStoreFailed. Logging remote store error.", ex); } @Override public void onFlowFinishFailed(RecordsChannel recordsChannel, Exception ex) { - Logger.warn(LOG_TAG, "Second RecordsChannel onFlowFinishedFailed. Reporting session error.", ex); - this.delegate.onSessionError(ex); + Logger.warn(LOG_TAG, "Second RecordsChannel onFlowFinishedFailed. Logging session error.", ex); + this.delegate.onSynchronizeFailed(this, ex, "Failed to finish second flow."); } /* * RepositorySessionCreationDelegate methods. */ /** * I could be called twice: once for sessionA and once for sessionB. @@ -256,67 +253,66 @@ implements RecordsChannelDelegate, this.context = null; this.sessionA.finish(this); } catch (Exception e) { // Never mind; best-effort finish. } } // We no longer need a reference to our context. this.context = null; - this.delegate.onSessionError(ex); + this.delegate.onSynchronizeFailed(this, ex, "Failed to create session"); } /** * I should be called twice: first for sessionA and second for sessionB. * * If I am called for sessionB, I call my delegate's `onInitialized` callback * method because my repository sessions are correctly initialized. */ // TODO: some of this "finish and clean up" code can be refactored out. @Override public void onSessionCreated(RepositorySession session) { if (session == null || this.sessionA == session) { // TODO: clean up sessionA. - this.delegate.onSessionError(new UnexpectedSessionException(session)); + this.delegate.onSynchronizeFailed(this, new UnexpectedSessionException(session), "Failed to create session."); return; } if (this.sessionA == null) { this.sessionA = session; // Unbundle. try { this.sessionA.unbundle(this.bundleA); } catch (Exception e) { - this.delegate.onSessionError(new UnbundleError(e, sessionA)); + this.delegate.onSynchronizeFailed(this, new UnbundleError(e, sessionA), "Failed to unbundle first session."); // TODO: abort return; } this.getSynchronizer().repositoryB.createSession(this, this.context); return; } if (this.sessionB == null) { this.sessionB = session; // We no longer need a reference to our context. this.context = null; // Unbundle. We unbundled sessionA when that session was created. try { this.sessionB.unbundle(this.bundleB); } catch (Exception e) { - // TODO: abort - this.delegate.onSessionError(new UnbundleError(e, sessionB)); + this.delegate.onSynchronizeFailed(this, new UnbundleError(e, sessionA), "Failed to unbundle second session."); return; } this.delegate.onInitialized(this); return; } // TODO: need a way to make sure we don't call any more delegate methods. - this.delegate.onSessionError(new UnexpectedSessionException(session)); + this.delegate.onSynchronizeFailed(this, new UnexpectedSessionException(session), "Failed to create session."); } /* * RepositorySessionFinishDelegate methods. */ /** * I could be called twice: once for sessionA and once for sessionB. @@ -349,37 +345,40 @@ implements RecordsChannelDelegate, if (session == sessionA) { if (flowAToBCompleted) { Logger.info(LOG_TAG, "onFinishSucceeded: bumping session A's timestamp to " + pendingATimestamp + " or " + storeEndATimestamp); bundle.bumpTimestamp(Math.max(pendingATimestamp, storeEndATimestamp)); this.synchronizer.bundleA = bundle; } else { // Should not happen! - this.delegate.onSessionError(new UnexpectedSessionException(sessionA)); + this.delegate.onSynchronizeFailed(this, new UnexpectedSessionException(sessionA), "Failed to finish first session."); + return; } if (this.sessionB != null) { Logger.info(LOG_TAG, "Finishing session B."); // On to the next. try { this.sessionB.finish(this); } catch (InactiveSessionException e) { this.onFinishFailed(e); + return; } } } else if (session == sessionB) { if (flowBToACompleted) { Logger.info(LOG_TAG, "onFinishSucceeded: bumping session B's timestamp to " + pendingBTimestamp + " or " + storeEndBTimestamp); bundle.bumpTimestamp(Math.max(pendingBTimestamp, storeEndBTimestamp)); this.synchronizer.bundleB = bundle; Logger.info(LOG_TAG, "Notifying delegate.onSynchronized."); this.delegate.onSynchronized(this); } else { // Should not happen! - this.delegate.onSessionError(new UnexpectedSessionException(sessionB)); + this.delegate.onSynchronizeFailed(this, new UnexpectedSessionException(sessionB), "Failed to finish second session."); + return; } } else { // TODO: hurrrrrr... } if (this.sessionB == null) { this.sessionA = null; // We're done. }
--- a/mobile/android/base/sync/synchronizer/SynchronizerSessionDelegate.java +++ b/mobile/android/base/sync/synchronizer/SynchronizerSessionDelegate.java @@ -4,17 +4,10 @@ package org.mozilla.gecko.sync.synchronizer; public interface SynchronizerSessionDelegate { public void onInitialized(SynchronizerSession session); public void onSynchronized(SynchronizerSession session); public void onSynchronizeFailed(SynchronizerSession session, Exception lastException, String reason); - public void onSynchronizeAborted(SynchronizerSession synchronizerSession); public void onSynchronizeSkipped(SynchronizerSession synchronizerSession); - - // TODO: return value? - public void onFetchError(Exception e); - public void onStoreError(Exception e); - public void onSessionError(Exception e); - }
--- a/mobile/android/sync/java-sources.mn +++ b/mobile/android/sync/java-sources.mn @@ -131,16 +131,17 @@ sync/repositories/domain/ClientRecord.ja sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/FormHistoryRecord.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.java sync/repositories/domain/VersionConstants.java +sync/repositories/FetchFailedException.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java @@ -152,18 +153,21 @@ sync/repositories/ParentNotFoundExceptio sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java +sync/repositories/StoreFailedException.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java +sync/Server11PreviousPostFailedException.java +sync/Server11RecordPostFailedException.java sync/setup/activities/AccountActivity.java sync/setup/activities/ActivityUtils.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/InvalidSyncKeyException.java sync/setup/SyncAccounts.java @@ -193,16 +197,18 @@ sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java +sync/synchronizer/ServerLocalSynchronizer.java +sync/synchronizer/ServerLocalSynchronizerSession.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java