|
16 | 16 | #include "application.h" |
17 | 17 | #include "configfile.h" |
18 | 18 |
|
19 | | -#include "fetchserversettings.h" |
| 19 | +// #include "fetchserversettings.h" |
| 20 | +#include "libsync/networkjobs/jsonjob.h" |
20 | 21 |
|
21 | 22 | #include "libsync/creds/abstractcredentials.h" |
22 | 23 |
|
@@ -56,6 +57,7 @@ AccountState::AccountState(Account *account) |
56 | 57 | , _waitingForNewCredentials(false) |
57 | 58 | , _connectionValidator(nullptr) |
58 | 59 | , _maintenanceToConnectedDelay(1min + minutes(QRandomGenerator::global()->generate() % 4)) // 1-5min delay |
| 60 | + , _needsServerSettingsRefresh(true) |
59 | 61 | { |
60 | 62 | qRegisterMetaType<AccountState *>("AccountState*"); |
61 | 63 |
|
@@ -187,29 +189,97 @@ void AccountState::setState(State state) |
187 | 189 | } |
188 | 190 | } |
189 | 191 |
|
190 | | - // might not have changed but the underlying _connectionErrors might have |
| 192 | + // only do this once when the state actually changes from something to connected |
| 193 | + // todo: need to investigate whether it's ever the case that we go from connected to connected. |
| 194 | + // so far it looks to me as if this happens when the connection validator confirms all is still well? |
191 | 195 | if (_state == Connected) { |
192 | | - QTimer::singleShot(0, this, [this, oldState] { |
193 | | - // ensure the connection validator is done |
194 | | - _queueGuard.unblock(); |
| 196 | + if (_needsServerSettingsRefresh) { |
195 | 197 | // update capabilities and fetch relevant settings |
196 | | - _fetchCapabilitiesJob = new FetchServerSettingsJob(_account, this); |
197 | | - connect(_fetchCapabilitiesJob.get(), &FetchServerSettingsJob::finishedSignal, this, [oldState, this] { |
198 | | - // Lisa todo: I do not understand this logic at all - review it |
199 | | - if (oldState == Connected || _state == Connected) { |
200 | | - _fetchCapabilitiesJob.clear(); |
201 | | - Q_EMIT isConnectedChanged(); |
202 | | - } |
203 | | - }); |
204 | | - _fetchCapabilitiesJob->start(); |
205 | | - }); |
| 198 | + // in the code path we unblock the queue *after* the caps retrieval has succeeded |
| 199 | + fetchServerSettings(); |
| 200 | + } else |
| 201 | + _queueGuard.unblock(); |
206 | 202 | } |
207 | 203 |
|
208 | 204 | if (oldState != _state) { |
209 | 205 | Q_EMIT stateChanged(_state); |
| 206 | + // the old->new state is confirmed to be different and one of them is connected state so |
| 207 | + // isConnected did actually change |
| 208 | + if (oldState == Connected || _state == Connected) |
| 209 | + emit isConnectedChanged(); |
| 210 | + } |
| 211 | +} |
| 212 | + |
| 213 | +void AccountState::fetchServerSettings() |
| 214 | +{ |
| 215 | + Q_ASSERT(_fetchServerSettingsRunner == nullptr); |
| 216 | + _fetchServerSettingsRunner = new FetchServerSettingsRunner(_account, this); |
| 217 | + |
| 218 | + connect(_fetchServerSettingsRunner, &FetchServerSettingsRunner::finishedSignal, this, &AccountState::slotFetchServerSettingsResult); |
| 219 | + _fetchServerSettingsRunner->start(); |
| 220 | +} |
| 221 | + |
| 222 | +void AccountState::slotFetchServerSettingsResult(FetchServerSettingsRunner::Result result) |
| 223 | +{ |
| 224 | + Q_ASSERT(_state == Connected); |
| 225 | + |
| 226 | + _connectionErrors.clear(); |
| 227 | + |
| 228 | + State newState = _state; |
| 229 | + |
| 230 | + switch (result) { |
| 231 | + case FetchServerSettingsRunner::Result::UnsupportedServer: |
| 232 | + _connectionErrors.append(tr("The server is not supported by this client.")); |
| 233 | + newState = ConfigurationError; |
| 234 | + break; |
| 235 | + case FetchServerSettingsRunner::Result::InvalidCredentials: |
| 236 | + slotInvalidCredentials(); |
| 237 | + break; |
| 238 | + case FetchServerSettingsRunner::Result::TimeOut: |
| 239 | + _connectionErrors.append(tr("Retrieving user settings and server capabilities timed out.")); |
| 240 | + // hmmm...do we need to retry in this case? I'm guessing yes but needs discussion |
| 241 | + // actually no, we should not need to do it explicitly as the next round(s) of connection validator should |
| 242 | + // hopefully resolve it |
| 243 | + newState = NetworkError; |
| 244 | + break; |
| 245 | + case FetchServerSettingsRunner::Result::Undefined: |
| 246 | + _connectionErrors.append(tr("Unable to retrieve user settings and server capabilities.")); |
| 247 | + newState = Disconnected; |
| 248 | + break; |
| 249 | + case FetchServerSettingsRunner::Result::Success: |
| 250 | + break; |
| 251 | + } |
| 252 | + |
| 253 | + // this step is done, delete after this slot finishes else the self deleting jobs inside get munged up -> crash. TODO: evaluate whether there is any |
| 254 | + // value to use the parenting mechanism for the AbstractNetworkJobs inside the FetchServerSettingsJob - I find it really questionable to parent |
| 255 | + // self deleting objects but this needs deeper investigation. |
| 256 | + _fetchServerSettingsRunner->deleteLater(); |
| 257 | + |
| 258 | + if (newState != Connected) { |
| 259 | + setState(newState); |
| 260 | + return; |
210 | 261 | } |
| 262 | + |
| 263 | + // these are both self deleting. |
| 264 | + // they can finish whenever, everything else can carry on. |
| 265 | + if (_account->capabilities().avatarsAvailable()) { |
| 266 | + auto *avatarJob = new AvatarJob(_account, _account->davUser(), 128, nullptr); |
| 267 | + connect(avatarJob, &AvatarJob::avatarPixmap, this, [this](const QPixmap &img) { _account->setAvatar(AvatarJob::makeCircularAvatar(img)); }); |
| 268 | + avatarJob->start(); |
| 269 | + } |
| 270 | + |
| 271 | + if (_account->capabilities().appProviders().enabled) { |
| 272 | + auto *jsonJob = new JsonJob(_account, _account->capabilities().appProviders().appsUrl, {}, "GET"); |
| 273 | + connect(jsonJob, &JsonJob::finishedSignal, this, [jsonJob, this] { _account->setAppProvider(AppProvider{jsonJob->data()}); }); |
| 274 | + jsonJob->start(); |
| 275 | + } |
| 276 | + |
| 277 | + _needsServerSettingsRefresh = false; |
| 278 | + _queueGuard.unblock(); |
| 279 | + emit isConnectedChanged(); |
211 | 280 | } |
212 | 281 |
|
| 282 | + |
213 | 283 | bool AccountState::isSignedOut() const |
214 | 284 | { |
215 | 285 | return _state == SignedOut; |
@@ -489,8 +559,6 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta |
489 | 559 | setState(Disconnected); |
490 | 560 | break; |
491 | 561 | case ConnectionValidator::ClientUnsupported: |
492 | | - [[fallthrough]]; |
493 | | - case ConnectionValidator::ServerVersionMismatch: |
494 | 562 | setState(ConfigurationError); |
495 | 563 | break; |
496 | 564 | case ConnectionValidator::StatusNotFound: |
@@ -543,6 +611,7 @@ void AccountState::slotInvalidCredentials() |
543 | 611 | qCInfo(lcAccountState) << "refreshing oauth failed"; |
544 | 612 | qCInfo(lcAccountState) << "asking user"; |
545 | 613 |
|
| 614 | + _needsServerSettingsRefresh = true; |
546 | 615 | creds->askFromUser(); |
547 | 616 | setState(AskingCredentials); |
548 | 617 | } |
@@ -590,7 +659,12 @@ void AccountState::setSettingUp(bool settingUp) |
590 | 659 | } |
591 | 660 | bool AccountState::readyForSync() const |
592 | 661 | { |
593 | | - return !_fetchCapabilitiesJob && isConnected(); |
| 662 | + // this is highly questionable. |
| 663 | + // first, this explains why the folders aren't ever syncing after refactoring the fetchServerSettings job. Folder::canSync calls this and |
| 664 | + // that is checked when trying to enqueue the folder |
| 665 | + // net is that because we can't cleanly get rid of the fetshServerSettingsJob (yet) this always returns false! or at least it does |
| 666 | + // on first folder load. |
| 667 | + return !_needsServerSettingsRefresh && isConnected(); |
594 | 668 | } |
595 | 669 |
|
596 | 670 | } // namespace OCC |
0 commit comments