Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync reset if browser was closed before the chain was fully created #3730

Closed
wants to merge 6 commits into from

Conversation

AlexeyBarabash
Copy link
Contributor

brave/brave-browser#6504

Submitter Checklist:

Test Plan:

From brave/brave-browser#6504

  1. Prepare clear profiles deviceA and deviceB
  2. Launch profile A, create new sync chain, ensure sync code is shown, but don't copy the code. Close deviceA.
  3. Launch profile B, create new sync chain, copy sync code, don't close.
  4. Launch profile A, enter sync code

Reviewer Checklist:

  • New files have MPL-2.0 license header.
  • Request a security/privacy review as needed.
  • Adequate test coverage exists to prevent regressions
  • Verify test plan is specified in PR before merging to source

After-merge Checklist:

  • The associated issue milestone is set to the smallest version that the
    changes has landed on.
  • All relevant documentation has been updated.

@AlexeyBarabash
Copy link
Contributor Author

CI marked this PR as UNSTABLE because BraveSystemRequestHandlerTest.AddBraveServiceKeyHeader had not passed

Copy link
Member

@darkdh darkdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Close browser is not the only way to interrupt sync chain setup process, closing sync page can do that. So we might also want to do the check when SyncUI is closed.
That needs ~SyncUIDOMHandler to inform BraveProfileSyncServiceImpl by OnSyncPageClosed and then we can do the check there. We can even only check incomplete sync chain setup there because when browser shutdown, the destructor will also be triggered.
It is also better to do this in shutdown rather than startup to prevent unnecessary loading sync extension.

// We want to reset the chain because it was not fully created
// We cannot make it here directly, because some sync classes may not be
// constructed yet
reseting_ = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this to trigger ResetSyncInternal() by ForceCompleteReset()?
If so, then we don't need to clear pref here https://github.com/brave/brave-core/pull/3730/files#diff-ab344835b09fb6ac1c601af787b116bbR184

Copy link
Contributor Author

@AlexeyBarabash AlexeyBarabash Oct 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this to trigger ResetSyncInternal() by ForceCompleteReset()?

yes

but if we don't reset devices list, UI page will never trigger BraveProfileSyncServiceImpl::OnSetupSyncHaveCode because device name is not empty https://github.com/brave/brave-core/blob/master/components/brave_sync/ui/components/modals/enterSyncCode.tsx#L92

so instead of clearing all prefs it would be enough co clean only the current device name, but I decided to clean all non-actual data

@AlexeyBarabash
Copy link
Contributor Author

Yes, also we can have this situation when browser process is killed or after power failure. So I don't want remove this check at startup.

Thanks for pointing to more elegant way in ~SyncUIDOMHandler , will expand the PR.

@AlexeyBarabash
Copy link
Contributor Author

I had made reset of sync prefs at BraveProfileSyncServiceImpl::Shutdown.

WebUI pages, if they passed sync words, and then are closed, they don't prevent the chain from creation. Another thing - we can have more than one opened brave://sync pages.

STR(1) to see the tab of brave://sync can be closed while chain creation.

1. Prepare clear profiles deviceA and deviceB
2. Launch profile A, create new sync chain, copy the sync code
3. Launch profile B, connect to the sync chain, paste sync code, don't wait for completion of chain creation, close the brave://sync tab.
4. On device A the brave://sync page shows two devices in chain
5. On device B open brave://sync tab and see two devices in chain

STR(2) to show an interesting case

1. Prepare clear profiles deviceA and deviceB
2. Launch profile A, create new sync chain, copy the sync code
3. Launch profile B, connect to the sync chain, paste sync code, press connect
4. When there will be two devices on device B, close device A
5. Launch device A, it is important the browser build don't have the commit of 2e5df197b0e53e612e9f75240132c8e94f53a1ba . The page brave://sync will show the sync is not initialized
6. Wait and after ~ 1 minute device A will show the sync chain is created with devices A and B

So with STR(2) the chain will be created. But we cannot distinguish such case and in the worst case the state of sync will be broken. So I made reset of sync prefs at BraveProfileSyncServiceImpl::Shutdown.

Copy link
Member

@darkdh darkdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the brave://sync closed case, I meant

  1. create sync chain on device A
  2. don't connect any device to device A
  3. close brave://sync on device A
  4. And sync is still enabled with only 1 device on sync chain even though sync UI is showing Screen Shot 2019-10-21 at 10 48 33

components/brave_sync/brave_profile_sync_service_impl.cc Outdated Show resolved Hide resolved
@AlexeyBarabash
Copy link
Contributor Author

Ah, you meant that.

IsSyncSetupIncomplete sounds better, modified, thanks.

@AlexeyBarabash AlexeyBarabash added the CI/skip Do not run CI builds (except noplatform) label Oct 31, 2019
@AlexeyBarabash AlexeyBarabash added enhancement and removed CI/skip Do not run CI builds (except noplatform) labels Nov 5, 2019
@AlexeyBarabash
Copy link
Contributor Author

Updated the PR to keep brave sync prefs in memory until the sync chain would have two or more devices.

// We are using latest device record until chain is not fully created
base::Time latest_device_record_time_;

NamedChangeCallback obs_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only allows one observer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as it is used only by one method in BraveProfileSyncServiceImpl, I decided to keep just one.

base::Time latest_device_record_time_;

NamedChangeCallback obs_;
void FireCallback(const std::string& name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be NotifyObserver or NotifyObservers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, thanks


namespace prefs {

class PrefsMemStore : public PrefsBase {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need PrefsBase? PrefsMemStore can be a subclass of Prefs and you can still do the switch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it was not required, but since PrefsMemStore would override all methods of Prefs, I did as it is there now.

std::make_unique<prefs::Prefs>(sync_client_->GetPrefService());
brave_sync_prefs_ = brave_sync_prefs_disk_store_.get();

if (IsSyncSetupIncomplete()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having IsBraveSyncInitialized, IsBraveSyncConfigured and IsSyncSetupIncomplete is just way too confusing. We need to simplify the possible states and add comments to explain what they are. Also we shouldn't mix the "positive" and "negative" forms of checks because that's also confusing to read. IsSyncSetupComplete is the "positive" form vs IsSyncSetupIncomplete

@@ -232,6 +253,17 @@ BraveProfileSyncServiceImpl::~BraveProfileSyncServiceImpl() {
network_connection_tracker_->RemoveNetworkConnectionObserver(this);
}

bool BraveProfileSyncServiceImpl::IsSyncSetupIncomplete() const {
auto devices = brave_sync_prefs_->GetSyncDevices();
if (devices->size() < 2 &&
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sync setup is not complete is more than one device?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, sync setup is not complete when have less than 2 devices

@@ -320,6 +352,7 @@ void BraveProfileSyncServiceImpl::OnResetSync() {
// We have to send delete record and wait for library deleted response then
// we can reset it by ResetSyncInternal()
const std::string device_id = brave_sync_prefs_->GetThisDeviceId();
DCHECK(!device_id.empty());
OnDeleteDevice(device_id);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we care about deleting devices if we're resetting sync?

Copy link
Member

@darkdh darkdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To summarize the discussion on Slack,

  1. We should only have states like enabled/initializing/initialized/ready
  2. Getting rids of brave_sync::Prefs class because it's mostly just calling get/set on the pref service anyway
  3. Only state that has transient data is initializing (seed and device id)
  4. Getting rids of all two devices check, ex. waiting for 2nd device when setup, reset sync chain when it comes down to 1 device, ... etc. Let UI flow handle the "at two devices on sync chain" requirement

@AlexeyBarabash
Copy link
Contributor Author

PR requires a lot of changes, so the reviewed points will be removed or redone.

@AlexeyBarabash
Copy link
Contributor Author

Closing this, as prefs are redone in #3988 according to #3730 (review)

@AlexeyBarabash AlexeyBarabash deleted the sync_reset_issue_6504 branch November 14, 2019 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants