summaryrefslogtreecommitdiff
path: root/chromium/components/sync_sessions
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 16:23:34 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-14 10:37:21 +0000
commit38a9a29f4f9436cace7f0e7abf9c586057df8a4e (patch)
treec4e8c458dc595bc0ddb435708fa2229edfd00bd4 /chromium/components/sync_sessions
parente684a3455bcc29a6e3e66a004e352dea4e1141e7 (diff)
downloadqtwebengine-chromium-38a9a29f4f9436cace7f0e7abf9c586057df8a4e.tar.gz
BASELINE: Update Chromium to 73.0.3683.37
Change-Id: I08c9af2948b645f671e5d933aca1f7a90ea372f2 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/sync_sessions')
-rw-r--r--chromium/components/sync_sessions/BUILD.gn2
-rw-r--r--chromium/components/sync_sessions/favicon_cache.cc57
-rw-r--r--chromium/components/sync_sessions/favicon_cache.h30
-rw-r--r--chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc4
-rw-r--r--chromium/components/sync_sessions/proxy_tabs_data_type_controller.cc95
-rw-r--r--chromium/components/sync_sessions/proxy_tabs_data_type_controller.h52
-rw-r--r--chromium/components/sync_sessions/session_store.cc24
-rw-r--r--chromium/components/sync_sessions/session_store.h7
-rw-r--r--chromium/components/sync_sessions/session_store_unittest.cc138
-rw-r--r--chromium/components/sync_sessions/session_sync_bridge.cc30
-rw-r--r--chromium/components/sync_sessions/session_sync_bridge_unittest.cc70
-rw-r--r--chromium/components/sync_sessions/session_sync_test_helper.cc42
-rw-r--r--chromium/components/sync_sessions/session_sync_test_helper.h16
13 files changed, 459 insertions, 108 deletions
diff --git a/chromium/components/sync_sessions/BUILD.gn b/chromium/components/sync_sessions/BUILD.gn
index 74028ef9af3..9be971c755a 100644
--- a/chromium/components/sync_sessions/BUILD.gn
+++ b/chromium/components/sync_sessions/BUILD.gn
@@ -15,6 +15,8 @@ static_library("sync_sessions") {
"open_tabs_ui_delegate.h",
"open_tabs_ui_delegate_impl.cc",
"open_tabs_ui_delegate_impl.h",
+ "proxy_tabs_data_type_controller.cc",
+ "proxy_tabs_data_type_controller.h",
"session_model_type_controller.cc",
"session_model_type_controller.h",
"session_store.cc",
diff --git a/chromium/components/sync_sessions/favicon_cache.cc b/chromium/components/sync_sessions/favicon_cache.cc
index 9a75025a6d8..53014c5f7cd 100644
--- a/chromium/components/sync_sessions/favicon_cache.cc
+++ b/chromium/components/sync_sessions/favicon_cache.cc
@@ -248,10 +248,9 @@ syncer::SyncMergeResult FaviconCache::MergeDataAndStartSyncing(
syncer::SyncMergeResult merge_result(type);
merge_result.set_num_items_before_association(synced_favicons_.size());
std::set<GURL> unsynced_favicon_urls;
- for (FaviconMap::const_iterator iter = synced_favicons_.begin();
- iter != synced_favicons_.end(); ++iter) {
- if (FaviconInfoHasValidTypeData(*(iter->second), type))
- unsynced_favicon_urls.insert(iter->first);
+ for (const auto& url_icon_pair : synced_favicons_) {
+ if (FaviconInfoHasValidTypeData(*url_icon_pair.second, type))
+ unsynced_favicon_urls.insert(url_icon_pair.first);
}
syncer::SyncChangeList local_changes;
@@ -406,10 +405,9 @@ void FaviconCache::OnPageFaviconUpdated(const GURL& page_url,
if (page_task_map_.find(page_url) != page_task_map_.end())
return;
- PageFaviconMap::const_iterator url_iter = page_favicon_map_.find(page_url);
+ auto url_iter = page_favicon_map_.find(page_url);
if (url_iter != page_favicon_map_.end()) {
- FaviconMap::const_iterator icon_iter =
- synced_favicons_.find(url_iter->second);
+ auto icon_iter = synced_favicons_.find(url_iter->second);
// TODO(zea): consider what to do when only a subset of supported
// resolutions are available.
if (icon_iter != synced_favicons_.end() &&
@@ -536,8 +534,8 @@ base::Time FaviconCache::GetLastVisitTimeForTest(
}
bool FaviconCache::FaviconRecencyFunctor::operator()(
- const linked_ptr<SyncedFaviconInfo>& lhs,
- const linked_ptr<SyncedFaviconInfo>& rhs) const {
+ const SyncedFaviconInfo* lhs,
+ const SyncedFaviconInfo* rhs) const {
// TODO(zea): incorporate bookmarked status here once we care about it.
if (lhs->last_visit_time < rhs->last_visit_time)
return true;
@@ -622,7 +620,7 @@ void FaviconCache::UpdateSyncState(
return;
}
- FaviconMap::const_iterator iter = synced_favicons_.find(icon_url);
+ auto iter = synced_favicons_.find(icon_url);
DCHECK(iter != synced_favicons_.end());
const SyncedFaviconInfo* favicon_info = iter->second.get();
@@ -675,32 +673,32 @@ SyncedFaviconInfo* FaviconCache::GetFaviconInfo(
// TODO(zea): implement in-memory eviction.
DVLOG(1) << "Adding favicon info for " << icon_url.spec();
- SyncedFaviconInfo* favicon_info = new SyncedFaviconInfo(icon_url);
- synced_favicons_[icon_url] = make_linked_ptr(favicon_info);
- recent_favicons_.insert(synced_favicons_[icon_url]);
+ auto favicon_info = std::make_unique<SyncedFaviconInfo>(icon_url);
+ SyncedFaviconInfo* favicon_info_ptr = favicon_info.get();
+ synced_favicons_[icon_url] = std::move(favicon_info);
+ recent_favicons_.insert(favicon_info_ptr);
DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size());
- return favicon_info;
+ return favicon_info_ptr;
}
void FaviconCache::UpdateFaviconVisitTime(const GURL& icon_url,
base::Time time) {
DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size());
- FaviconMap::const_iterator iter = synced_favicons_.find(icon_url);
+ auto iter = synced_favicons_.find(icon_url);
DCHECK(iter != synced_favicons_.end());
if (iter->second->last_visit_time >= time)
return;
// Erase, update the time, then re-insert to maintain ordering.
- recent_favicons_.erase(iter->second);
+ recent_favicons_.erase(iter->second.get());
DVLOG(1) << "Updating " << icon_url.spec() << " visit time to "
<< syncer::GetTimeDebugString(time);
iter->second->last_visit_time = time;
- recent_favicons_.insert(iter->second);
+ recent_favicons_.insert(iter->second.get());
if (VLOG_IS_ON(2)) {
- for (auto iter = recent_favicons_.begin(); iter != recent_favicons_.end();
- ++iter) {
- DVLOG(2) << "Favicon " << iter->get()->favicon_url.spec() << ": "
- << syncer::GetTimeDebugString(iter->get()->last_visit_time);
+ for (const auto* icon : recent_favicons_) {
+ DVLOG(2) << "Favicon " << icon->favicon_url.spec() << ": "
+ << syncer::GetTimeDebugString(icon->last_visit_time);
}
}
DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size());
@@ -717,7 +715,7 @@ void FaviconCache::ExpireFaviconsIfNecessary(
// already in recency order, so just start from the beginning.
// TODO(zea): to reduce thrashing, consider removing more than the minimum.
while (recent_favicons_.size() > max_sync_favicon_limit_) {
- linked_ptr<SyncedFaviconInfo> candidate = *recent_favicons_.begin();
+ SyncedFaviconInfo* candidate = *recent_favicons_.begin();
DVLOG(1) << "Expiring favicon " << candidate->favicon_url.spec();
DeleteSyncedFavicon(synced_favicons_.find(candidate->favicon_url),
image_changes,
@@ -740,7 +738,7 @@ void FaviconCache::MergeSyncFavicon(const syncer::SyncData& sync_favicon,
DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING);
sync_pb::EntitySpecifics new_specifics;
GURL favicon_url = GetFaviconURLFromSpecifics(sync_favicon.GetSpecifics());
- FaviconMap::const_iterator iter = synced_favicons_.find(favicon_url);
+ auto iter = synced_favicons_.find(favicon_url);
DCHECK(iter != synced_favicons_.end());
SyncedFaviconInfo* favicon_info = iter->second.get();
if (type == syncer::FAVICON_IMAGES) {
@@ -910,7 +908,7 @@ void FaviconCache::DeleteSyncedFavicon(
FaviconMap::iterator favicon_iter,
syncer::SyncChangeList* image_changes,
syncer::SyncChangeList* tracking_changes) {
- linked_ptr<SyncedFaviconInfo> favicon_info = favicon_iter->second;
+ SyncedFaviconInfo* favicon_info = favicon_iter->second.get();
if (FaviconInfoHasImages(*(favicon_iter->second))) {
DVLOG(1) << "Deleting image for "
<< favicon_iter->second.get()->favicon_url;
@@ -937,10 +935,9 @@ void FaviconCache::DeleteSyncedFavicon(
void FaviconCache::DropSyncedFavicon(FaviconMap::iterator favicon_iter) {
DVLOG(1) << "Dropping favicon " << favicon_iter->second.get()->favicon_url;
const GURL& url = favicon_iter->first;
- recent_favicons_.erase(favicon_iter->second);
- base::EraseIf(page_favicon_map_, [url](const PageFaviconMap::value_type& kv) {
- return kv.second == url;
- });
+ recent_favicons_.erase(favicon_iter->second.get());
+ base::EraseIf(page_favicon_map_,
+ [url](const auto& kv) { return kv.second == url; });
synced_favicons_.erase(favicon_iter);
}
@@ -976,10 +973,10 @@ void FaviconCache::DropPartialFavicon(FaviconMap::iterator favicon_iter,
DCHECK_EQ(type, syncer::FAVICON_TRACKING);
DVLOG(1) << "Dropping favicon tracking "
<< favicon_iter->second.get()->favicon_url;
- recent_favicons_.erase(favicon_iter->second);
+ recent_favicons_.erase(favicon_iter->second.get());
favicon_iter->second->last_visit_time = base::Time();
favicon_iter->second->is_bookmarked = false;
- recent_favicons_.insert(favicon_iter->second);
+ recent_favicons_.insert(favicon_iter->second.get());
DCHECK(!FaviconInfoHasTracking(*favicon_iter->second));
}
}
diff --git a/chromium/components/sync_sessions/favicon_cache.h b/chromium/components/sync_sessions/favicon_cache.h
index 378b15d54b8..292636af11c 100644
--- a/chromium/components/sync_sessions/favicon_cache.h
+++ b/chromium/components/sync_sessions/favicon_cache.h
@@ -17,7 +17,6 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
@@ -118,19 +117,14 @@ class FaviconCache : public syncer::SyncableService,
// Functor for ordering SyncedFaviconInfo objects by recency;
struct FaviconRecencyFunctor {
- bool operator()(const linked_ptr<SyncedFaviconInfo>& lhs,
- const linked_ptr<SyncedFaviconInfo>& rhs) const;
+ bool operator()(const SyncedFaviconInfo* lhs,
+ const SyncedFaviconInfo* rhs) const;
};
// Map of favicon url to favicon image.
- using FaviconMap = std::map<GURL, linked_ptr<SyncedFaviconInfo>>;
- using RecencySet =
- std::set<linked_ptr<SyncedFaviconInfo>, FaviconRecencyFunctor>;
- // Map of page url to task id (for favicon loading).
- using PageTaskMap = std::map<GURL, base::CancelableTaskTracker::TaskId>;
- // Map of page url to favicon url.
- using PageFaviconMap = std::map<GURL, GURL>;
+ using FaviconMap = std::map<GURL, std::unique_ptr<SyncedFaviconInfo>>;
+ using RecencySet = std::set<SyncedFaviconInfo*, FaviconRecencyFunctor>;
// Callback method to store a tab's favicon into its sync node once it becomes
// available. Does nothing if no favicon data was available.
@@ -153,8 +147,8 @@ class FaviconCache : public syncer::SyncableService,
// |synced_favicons_| and |recent_favicons_| and returns it.
SyncedFaviconInfo* GetFaviconInfo(const GURL& icon_url);
- // Updates the last visit time for the favicon at |icon_url| to |time| (and
- // correspondly updates position in |recent_favicons_|.
+ // Updates the last visit time for the favicon at |icon_url| to |time| and
+ // correspondingly updates position in |recent_favicons_|.
void UpdateFaviconVisitTime(const GURL& icon_url, base::Time time);
// Expiration method. Looks through |recent_favicons_| to find any favicons
@@ -205,21 +199,21 @@ class FaviconCache : public syncer::SyncableService,
favicon::FaviconService* favicon_service_;
- // Trask tracker for loading favicons.
+ // Task tracker for loading favicons.
base::CancelableTaskTracker cancelable_task_tracker_;
- // Our actual cached favicon data.
+ // Our actual cached favicon data. Owns the favicons.
FaviconMap synced_favicons_;
// An LRU ordering of the favicons comprising |synced_favicons_| (oldest to
// newest).
RecencySet recent_favicons_;
- // Our set of pending favicon loads, indexed by page url.
- PageTaskMap page_task_map_;
+ // Pending favicon loads, map of page url to task id.
+ std::map<GURL, base::CancelableTaskTracker::TaskId> page_task_map_;
- // Map of page and associated favicon urls.
- PageFaviconMap page_favicon_map_;
+ // Map of page url to favicon url.
+ std::map<GURL, GURL> page_favicon_map_;
// TODO(zea): consider creating a favicon handler here for fetching unsynced
// favicons from the web.
diff --git a/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc b/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc
index 856fd9cf670..495e6a0d638 100644
--- a/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc
+++ b/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc
@@ -7,8 +7,8 @@
#include <memory>
#include <string>
-#include "base/message_loop/message_loop.h"
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_task_environment.h"
#include "components/sync/syncable/entry.h"
#include "components/sync/syncable/mutable_entry.h"
#include "components/sync/syncable/syncable_base_transaction.h"
@@ -121,7 +121,7 @@ class LostNavigationsRecorderTest : public testing::Test {
}
private:
- base::MessageLoop message_loop;
+ base::test::ScopedTaskEnvironment task_environment_;
int _id;
LostNavigationsRecorder recorder_;
syncer::TestDirectorySetterUpper dir_maker_;
diff --git a/chromium/components/sync_sessions/proxy_tabs_data_type_controller.cc b/chromium/components/sync_sessions/proxy_tabs_data_type_controller.cc
new file mode 100644
index 00000000000..ca6743edc49
--- /dev/null
+++ b/chromium/components/sync_sessions/proxy_tabs_data_type_controller.cc
@@ -0,0 +1,95 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync_sessions/proxy_tabs_data_type_controller.h"
+
+#include <utility>
+
+#include "base/values.h"
+#include "components/sync/driver/configure_context.h"
+#include "components/sync/engine/model_safe_worker.h"
+#include "components/sync/engine/model_type_configurer.h"
+#include "components/sync/model/sync_merge_result.h"
+
+namespace sync_sessions {
+
+ProxyTabsDataTypeController::ProxyTabsDataTypeController(
+ const base::RepeatingCallback<void(State)>& state_changed_cb)
+ : DataTypeController(syncer::PROXY_TABS),
+ state_changed_cb_(state_changed_cb),
+ state_(NOT_RUNNING) {}
+
+ProxyTabsDataTypeController::~ProxyTabsDataTypeController() {}
+
+bool ProxyTabsDataTypeController::ShouldLoadModelBeforeConfigure() const {
+ return false;
+}
+
+void ProxyTabsDataTypeController::BeforeLoadModels(
+ syncer::ModelTypeConfigurer* configurer) {
+ // Proxy type doesn't need to be registered with ModelTypeRegistry as it
+ // doesn't need update handler, client doesn't expect updates of this type
+ // from the server. We still need to register proxy type because
+ // AddClientConfigParamsToMessage decides the value of tabs_datatype_enabled
+ // based on presence of proxy types in the set of enabled types.
+ configurer->RegisterDirectoryDataType(type(), syncer::GROUP_PASSIVE);
+}
+
+void ProxyTabsDataTypeController::LoadModels(
+ const syncer::ConfigureContext& configure_context,
+ const ModelLoadCallback& model_load_callback) {
+ DCHECK(CalledOnValidThread());
+ DCHECK_EQ(configure_context.storage_option, syncer::STORAGE_ON_DISK);
+ state_ = MODEL_LOADED;
+ state_changed_cb_.Run(state_);
+ model_load_callback.Run(type(), syncer::SyncError());
+}
+
+void ProxyTabsDataTypeController::RegisterWithBackend(
+ base::OnceCallback<void(bool)> set_downloaded,
+ syncer::ModelTypeConfigurer* configurer) {}
+
+void ProxyTabsDataTypeController::StartAssociating(
+ StartCallback start_callback) {
+ DCHECK(CalledOnValidThread());
+ syncer::SyncMergeResult local_merge_result(type());
+ syncer::SyncMergeResult syncer_merge_result(type());
+ state_ = RUNNING;
+ state_changed_cb_.Run(state_);
+ std::move(start_callback)
+ .Run(DataTypeController::OK, local_merge_result, syncer_merge_result);
+}
+
+void ProxyTabsDataTypeController::Stop(syncer::ShutdownReason shutdown_reason,
+ StopCallback callback) {
+ state_ = NOT_RUNNING;
+ state_changed_cb_.Run(state_);
+ std::move(callback).Run();
+}
+
+syncer::DataTypeController::State ProxyTabsDataTypeController::state() const {
+ return state_;
+}
+
+void ProxyTabsDataTypeController::ActivateDataType(
+ syncer::ModelTypeConfigurer* configurer) {}
+
+void ProxyTabsDataTypeController::DeactivateDataType(
+ syncer::ModelTypeConfigurer* configurer) {
+ configurer->UnregisterDirectoryDataType(type());
+}
+
+void ProxyTabsDataTypeController::GetAllNodes(AllNodesCallback callback) {
+ std::move(callback).Run(type(), std::make_unique<base::ListValue>());
+}
+
+void ProxyTabsDataTypeController::GetStatusCounters(
+ StatusCountersCallback callback) {
+ syncer::StatusCounters counters;
+ std::move(callback).Run(type(), counters);
+}
+
+void ProxyTabsDataTypeController::RecordMemoryUsageAndCountsHistograms() {}
+
+} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/proxy_tabs_data_type_controller.h b/chromium/components/sync_sessions/proxy_tabs_data_type_controller.h
new file mode 100644
index 00000000000..9d31df7c331
--- /dev/null
+++ b/chromium/components/sync_sessions/proxy_tabs_data_type_controller.h
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SYNC_SESSIONS_PROXY_TABS_DATA_TYPE_CONTROLLER_H_
+#define COMPONENTS_SYNC_SESSIONS_PROXY_TABS_DATA_TYPE_CONTROLLER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "components/sync/driver/data_type_controller.h"
+
+namespace sync_sessions {
+
+// Controller for PROXY_TABS. Proxy tabs have no representation in sync, and
+// therefore processor or worker.
+class ProxyTabsDataTypeController : public syncer::DataTypeController {
+ public:
+ // |state_changed_cb| can be used to listen to state changes.
+ explicit ProxyTabsDataTypeController(
+ const base::RepeatingCallback<void(State)>& state_changed_cb);
+ ~ProxyTabsDataTypeController() override;
+
+ // DataTypeController interface.
+ bool ShouldLoadModelBeforeConfigure() const override;
+ void BeforeLoadModels(syncer::ModelTypeConfigurer* configurer) override;
+ void LoadModels(const syncer::ConfigureContext& configure_context,
+ const ModelLoadCallback& model_load_callback) override;
+ void RegisterWithBackend(base::OnceCallback<void(bool)> set_downloaded,
+ syncer::ModelTypeConfigurer* configurer) override;
+ void StartAssociating(StartCallback start_callback) override;
+ void Stop(syncer::ShutdownReason shutdown_reason,
+ StopCallback callback) override;
+ State state() const override;
+ void ActivateDataType(syncer::ModelTypeConfigurer* configurer) override;
+ void DeactivateDataType(syncer::ModelTypeConfigurer* configurer) override;
+ void GetAllNodes(AllNodesCallback callback) override;
+ void GetStatusCounters(StatusCountersCallback callback) override;
+ void RecordMemoryUsageAndCountsHistograms() override;
+
+ private:
+ const base::RepeatingCallback<void(State)> state_changed_cb_;
+ State state_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProxyTabsDataTypeController);
+};
+
+} // namespace sync_sessions
+
+#endif // COMPONENTS_SYNC_SESSIONS_PROXY_TABS_DATA_TYPE_CONTROLLER_H_
diff --git a/chromium/components/sync_sessions/session_store.cc b/chromium/components/sync_sessions/session_store.cc
index 35885a8aad2..d91625e0547 100644
--- a/chromium/components/sync_sessions/session_store.cc
+++ b/chromium/components/sync_sessions/session_store.cc
@@ -244,7 +244,8 @@ std::string SessionStore::WriteBatch::PutAndUpdateTracker(
return PutWithoutUpdatingTracker(specifics);
}
-void SessionStore::WriteBatch::DeleteForeignEntityAndUpdateTracker(
+std::vector<std::string>
+SessionStore::WriteBatch::DeleteForeignEntityAndUpdateTracker(
const std::string& storage_key) {
std::string session_tag;
int tab_node_id;
@@ -252,11 +253,23 @@ void SessionStore::WriteBatch::DeleteForeignEntityAndUpdateTracker(
DCHECK(success);
DCHECK_NE(session_tag, session_tracker_->GetLocalSessionTag());
+ std::vector<std::string> deleted_storage_keys;
+ deleted_storage_keys.push_back(storage_key);
+
if (tab_node_id == TabNodePool::kInvalidTabNodeID) {
- // Removal of a foreign header entity.
- // TODO(mastiz): This cascades with the removal of tabs too. Should we
- // reflect this as batch_->DeleteData()? The old code didn't, presumably
- // because we expect the rest of the removals to follow.
+ // Removal of a foreign header entity cascades the deletion of all tabs in
+ // the same session too.
+ for (int cascading_tab_node_id :
+ session_tracker_->LookupTabNodeIds(session_tag)) {
+ std::string tab_storage_key =
+ GetTabStorageKey(session_tag, cascading_tab_node_id);
+ // Note that DeleteForeignSession() below takes care of removing all tabs
+ // from the tracker, so no DeleteForeignTab() needed.
+ batch_->DeleteData(tab_storage_key);
+ deleted_storage_keys.push_back(std::move(tab_storage_key));
+ }
+
+ // Delete session itself.
session_tracker_->DeleteForeignSession(session_tag);
} else {
// Removal of a foreign tab entity.
@@ -264,6 +277,7 @@ void SessionStore::WriteBatch::DeleteForeignEntityAndUpdateTracker(
}
batch_->DeleteData(storage_key);
+ return deleted_storage_keys;
}
std::string SessionStore::WriteBatch::PutWithoutUpdatingTracker(
diff --git a/chromium/components/sync_sessions/session_store.h b/chromium/components/sync_sessions/session_store.h
index db2746332e2..80d95446476 100644
--- a/chromium/components/sync_sessions/session_store.h
+++ b/chromium/components/sync_sessions/session_store.h
@@ -94,10 +94,13 @@ class SessionStore {
SyncedSessionTracker* session_tracker);
~WriteBatch();
- // Most mutations below return a storage key.
+ // Most mutations below return storage keys.
std::string PutAndUpdateTracker(const sync_pb::SessionSpecifics& specifics,
base::Time modification_time);
- void DeleteForeignEntityAndUpdateTracker(const std::string& storage_key);
+ // Returns all deleted storage keys, which may be more than one if
+ // |storage_key| refers to a header entity.
+ std::vector<std::string> DeleteForeignEntityAndUpdateTracker(
+ const std::string& storage_key);
// The functions below do not update SyncedSessionTracker and hence it is
// the caller's responsibility to do so *before* calling these functions.
std::string PutWithoutUpdatingTracker(
diff --git a/chromium/components/sync_sessions/session_store_unittest.cc b/chromium/components/sync_sessions/session_store_unittest.cc
index 2a4aab806d3..1517cce4313 100644
--- a/chromium/components/sync_sessions/session_store_unittest.cc
+++ b/chromium/components/sync_sessions/session_store_unittest.cc
@@ -9,9 +9,9 @@
#include <vector>
#include "base/bind_helpers.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync/base/hash_util.h"
#include "components/sync/device_info/device_info.h"
@@ -180,7 +180,7 @@ class SessionStoreFactoryTest : public ::testing::Test {
~SessionStoreFactoryTest() override {}
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
const syncer::DeviceInfo local_device_info_;
TestingPrefServiceSimple pref_service_;
SessionSyncPrefs session_sync_prefs_;
@@ -497,6 +497,140 @@ TEST_F(SessionStoreTest, ShouldWriteAndRestoreForeignData) {
/*urls=*/_)))));
}
+TEST_F(SessionStoreTest, ShouldDeleteForeignData) {
+ const std::string kForeignSessionTag = "SomeForeignTag";
+ const int kWindowId = 5;
+ const int kTabId1 = 7;
+ const int kTabId2 = 8;
+ const int kTabNodeId1 = 1;
+ const int kTabNodeId2 = 2;
+
+ EXPECT_CALL(mock_restored_foreign_tab_callback_, Run(_, _)).Times(0);
+
+ const std::string local_header_storage_key =
+ SessionStore::GetHeaderStorageKey(kLocalSessionTag);
+
+ // Local session is automatically created.
+ ASSERT_THAT(BatchToEntityDataMap(session_store()->GetAllSessionData()),
+ ElementsAre(Pair(local_header_storage_key, _)));
+ ASSERT_THAT(ReadAllPersistedDataFrom(underlying_store_.get()), IsEmpty());
+
+ // Populate with foreign data: one header entity and two tabs.
+ SessionSpecifics header;
+ header.set_session_tag(kForeignSessionTag);
+ header.mutable_header()->add_window()->set_window_id(kWindowId);
+ header.mutable_header()->mutable_window(0)->add_tab(kTabId1);
+ header.mutable_header()->mutable_window(0)->add_tab(kTabId2);
+ ASSERT_TRUE(SessionStore::AreValidSpecifics(header));
+
+ SessionSpecifics tab1;
+ tab1.set_session_tag(kForeignSessionTag);
+ tab1.set_tab_node_id(kTabNodeId1);
+ tab1.mutable_tab()->set_window_id(kWindowId);
+ tab1.mutable_tab()->set_tab_id(kTabId1);
+ ASSERT_TRUE(SessionStore::AreValidSpecifics(tab1));
+
+ SessionSpecifics tab2;
+ tab2.set_session_tag(kForeignSessionTag);
+ tab2.set_tab_node_id(kTabNodeId2);
+ tab2.mutable_tab()->set_window_id(kWindowId);
+ tab2.mutable_tab()->set_tab_id(kTabId2);
+ ASSERT_TRUE(SessionStore::AreValidSpecifics(tab2));
+
+ const std::string header_storage_key =
+ SessionStore::GetHeaderStorageKey(kForeignSessionTag);
+ const std::string tab_storage_key1 =
+ SessionStore::GetTabStorageKey(kForeignSessionTag, kTabNodeId1);
+ const std::string tab_storage_key2 =
+ SessionStore::GetTabStorageKey(kForeignSessionTag, kTabNodeId2);
+
+ // Write data and update the tracker.
+ {
+ std::unique_ptr<SessionStore::WriteBatch> batch =
+ session_store()->CreateWriteBatch(/*error_handler=*/base::DoNothing());
+ ASSERT_THAT(batch, NotNull());
+ batch->PutAndUpdateTracker(header, base::Time::Now());
+ batch->PutAndUpdateTracker(tab1, base::Time::Now());
+ batch->PutAndUpdateTracker(tab2, base::Time::Now());
+
+ sync_pb::EntityMetadata header_metadata;
+ header_metadata.set_server_id("someserverid1");
+ batch->GetMetadataChangeList()->UpdateMetadata(header_storage_key,
+ header_metadata);
+
+ sync_pb::EntityMetadata tab1_metadata;
+ tab1_metadata.set_server_id("someserverid2");
+ batch->GetMetadataChangeList()->UpdateMetadata(tab_storage_key1,
+ tab1_metadata);
+
+ sync_pb::EntityMetadata tab2_metadata;
+ tab2_metadata.set_server_id("someserverid3");
+ batch->GetMetadataChangeList()->UpdateMetadata(tab_storage_key2,
+ tab2_metadata);
+ SessionStore::WriteBatch::Commit(std::move(batch));
+ }
+
+ // Verify the underlying storage contains the data.
+ ASSERT_THAT(
+ ReadAllPersistedDataFrom(underlying_store_.get()),
+ UnorderedElementsAre(
+ Pair(header_storage_key,
+ MatchesHeader(kForeignSessionTag, {kWindowId},
+ {kTabId1, kTabId2})),
+ Pair(tab_storage_key1,
+ MatchesTab(kForeignSessionTag, kWindowId, kTabId1, kTabNodeId1,
+ /*urls=*/_)),
+ Pair(tab_storage_key2,
+ MatchesTab(kForeignSessionTag, kWindowId, kTabId2, kTabNodeId2,
+ /*urls=*/_))));
+
+ // Verify tracker exposes the foreign tabs.
+ ASSERT_THAT(session_store()->tracker()->LookupAllForeignSessions(
+ SyncedSessionTracker::RAW),
+ ElementsAre(MatchesSyncedSession(
+ kForeignSessionTag,
+ {{kWindowId, std::vector<int>{kTabId1, kTabId2}}})));
+
+ // Mimic receiving a tab deletion for |tab1|, which should only affect that
+ // entity.
+ {
+ std::unique_ptr<SessionStore::WriteBatch> batch =
+ session_store()->CreateWriteBatch(/*error_handler=*/base::DoNothing());
+
+ EXPECT_THAT(batch->DeleteForeignEntityAndUpdateTracker(tab_storage_key1),
+ ElementsAre(tab_storage_key1));
+
+ SessionStore::WriteBatch::Commit(std::move(batch));
+ }
+
+ EXPECT_THAT(
+ ReadAllPersistedDataFrom(underlying_store_.get()),
+ UnorderedElementsAre(
+ Pair(header_storage_key,
+ MatchesHeader(kForeignSessionTag, {kWindowId},
+ {kTabId1, kTabId2})),
+ Pair(tab_storage_key2,
+ MatchesTab(kForeignSessionTag, kWindowId, kTabId2, kTabNodeId2,
+ /*urls=*/_))));
+
+ // Mimic receiving a header deletion (which should delete all remaining
+ // entities for that session).
+ {
+ std::unique_ptr<SessionStore::WriteBatch> batch =
+ session_store()->CreateWriteBatch(/*error_handler=*/base::DoNothing());
+
+ EXPECT_THAT(batch->DeleteForeignEntityAndUpdateTracker(header_storage_key),
+ ElementsAre(header_storage_key, tab_storage_key2));
+
+ SessionStore::WriteBatch::Commit(std::move(batch));
+ }
+
+ EXPECT_THAT(session_store()->tracker()->LookupAllForeignSessions(
+ SyncedSessionTracker::RAW),
+ IsEmpty());
+ EXPECT_THAT(ReadAllPersistedDataFrom(underlying_store_.get()), IsEmpty());
+}
+
TEST_F(SessionStoreTest, ShouldReturnForeignUnmappedTabs) {
const std::string kForeignSessionTag = "SomeForeignTag";
const int kWindowId = 5;
diff --git a/chromium/components/sync_sessions/session_sync_bridge.cc b/chromium/components/sync_sessions/session_sync_bridge.cc
index 68b83d5b8ed..b9956b5b004 100644
--- a/chromium/components/sync_sessions/session_sync_bridge.cc
+++ b/chromium/components/sync_sessions/session_sync_bridge.cc
@@ -211,7 +211,16 @@ base::Optional<syncer::ModelError> SessionSyncBridge::ApplySyncChanges(
<< "local navigation event.";
syncing_->local_data_out_of_sync = true;
} else {
- batch->DeleteForeignEntityAndUpdateTracker(change.storage_key());
+ // Deleting an entity (if it's a header entity) may cascade other
+ // deletions, so let's assume that whoever initiated remote deletions
+ // must have taken care of deleting them all. We don't have to commit
+ // these deletions, simply delete all local sync metadata (untrack).
+ for (const std::string& deleted_storage_key :
+ batch->DeleteForeignEntityAndUpdateTracker(
+ change.storage_key())) {
+ change_processor()->UntrackEntityForStorageKey(deleted_storage_key);
+ metadata_change_list->ClearMetadata(deleted_storage_key);
+ }
}
break;
case syncer::EntityChange::ACTION_ADD:
@@ -434,21 +443,14 @@ void SessionSyncBridge::DeleteForeignSessionWithBatch(
return;
}
- // Delete tabs.
- for (int tab_node_id :
- syncing_->store->tracker()->LookupTabNodeIds(session_tag)) {
- const std::string tab_storage_key =
- SessionStore::GetTabStorageKey(session_tag, tab_node_id);
- batch->DeleteForeignEntityAndUpdateTracker(tab_storage_key);
- change_processor()->Delete(tab_storage_key, batch->GetMetadataChangeList());
- }
-
- // Delete header.
+ // Deleting the header entity cascades the deletions of tabs as well.
const std::string header_storage_key =
SessionStore::GetHeaderStorageKey(session_tag);
- batch->DeleteForeignEntityAndUpdateTracker(header_storage_key);
- change_processor()->Delete(header_storage_key,
- batch->GetMetadataChangeList());
+ for (const std::string& deleted_storage_key :
+ batch->DeleteForeignEntityAndUpdateTracker(header_storage_key)) {
+ change_processor()->Delete(deleted_storage_key,
+ batch->GetMetadataChangeList());
+ }
notify_foreign_session_updated_cb_.Run();
}
diff --git a/chromium/components/sync_sessions/session_sync_bridge_unittest.cc b/chromium/components/sync_sessions/session_sync_bridge_unittest.cc
index c9ac15f2213..47a81ffcf9d 100644
--- a/chromium/components/sync_sessions/session_sync_bridge_unittest.cc
+++ b/chromium/components/sync_sessions/session_sync_bridge_unittest.cc
@@ -11,11 +11,11 @@
#include "base/bind_helpers.h"
#include "base/json/json_writer.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind_test_util.h"
#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync/base/hash_util.h"
#include "components/sync/base/sync_prefs.h"
@@ -323,8 +323,10 @@ class SessionSyncBridgeTest : public ::testing::Test {
return real_processor_.get();
}
+ syncer::ModelTypeStore* underlying_store() { return store_.get(); }
+
private:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
const syncer::DeviceInfo local_device_info_;
const std::unique_ptr<syncer::ModelTypeStore> store_;
@@ -1139,6 +1141,17 @@ TEST_F(SessionSyncBridgeTest, ShouldHandleRemoteDeletion) {
kForeignTabNodeId, "http://baz.com/");
StartSyncing({foreign_header, foreign_tab});
+ sync_pb::ModelTypeState state;
+ state.set_initial_sync_done(true);
+
+ // Mimic receiving a commit ack for the local header entity, to later be able
+ // to verify HasLocalChangesForTest() without interferences from the local
+ // session.
+ ASSERT_TRUE(real_processor()->HasLocalChangesForTest());
+ real_processor()->OnCommitCompleted(
+ state, {CreateSuccessResponse(kLocalSessionTag)});
+ ASSERT_FALSE(real_processor()->HasLocalChangesForTest());
+
const sessions::SessionTab* foreign_session_tab = nullptr;
ASSERT_TRUE(bridge()->GetOpenTabsUIDelegate()->GetForeignTab(
kForeignSessionTag, SessionID::FromSerializedValue(kForeignTabId),
@@ -1152,11 +1165,13 @@ TEST_F(SessionSyncBridgeTest, ShouldHandleRemoteDeletion) {
kForeignSessionTag,
{{kForeignWindowId, std::vector<int>{kForeignTabId}}})));
ASSERT_TRUE(real_processor()->IsTrackingMetadata());
+ ASSERT_TRUE(real_processor()->IsTrackingEntityForTest(
+ SessionStore::GetHeaderStorageKey(kForeignSessionTag)));
+ ASSERT_TRUE(real_processor()->IsTrackingEntityForTest(
+ SessionStore::GetTabStorageKey(kForeignSessionTag, kForeignTabNodeId)));
+ ASSERT_FALSE(real_processor()->HasLocalChangesForTest());
// Mimic receiving a remote deletion of the foreign session.
- sync_pb::ModelTypeState state;
- state.set_initial_sync_done(true);
-
EXPECT_CALL(mock_foreign_session_updated_cb(), Run());
real_processor()->OnUpdateReceived(
state, {CreateTombstone(SessionStore::GetClientTag(foreign_header))});
@@ -1168,6 +1183,51 @@ TEST_F(SessionSyncBridgeTest, ShouldHandleRemoteDeletion) {
EXPECT_FALSE(bridge()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
&foreign_sessions));
+
+ EXPECT_FALSE(real_processor()->HasLocalChangesForTest());
+
+ const std::string header_storage_key =
+ SessionStore::GetHeaderStorageKey(kForeignSessionTag);
+ const std::string tab_storage_key =
+ SessionStore::GetTabStorageKey(kForeignSessionTag, kForeignTabNodeId);
+
+ EXPECT_FALSE(real_processor()->IsTrackingEntityForTest(header_storage_key));
+ EXPECT_FALSE(real_processor()->IsTrackingEntityForTest(tab_storage_key));
+
+ // Verify that both entities have been deleted from storage.
+ {
+ base::RunLoop loop;
+ underlying_store()->ReadData(
+ {header_storage_key, tab_storage_key},
+ base::BindLambdaForTesting(
+ [&](const base::Optional<syncer::ModelError>& error,
+ std::unique_ptr<syncer::ModelTypeStore::RecordList>
+ data_records,
+ std::unique_ptr<syncer::ModelTypeStore::IdList>
+ missing_id_list) {
+ EXPECT_THAT(data_records, Pointee(IsEmpty()));
+ EXPECT_THAT(
+ missing_id_list,
+ Pointee(ElementsAre(header_storage_key, tab_storage_key)));
+ loop.Quit();
+ }));
+ loop.Run();
+ }
+
+ // Verify that the sync metadata for both entities have been deleted too.
+ {
+ base::RunLoop loop;
+ underlying_store()->ReadAllMetadata(base::BindLambdaForTesting(
+ [&](const base::Optional<syncer::ModelError>& error,
+ std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
+ syncer::EntityMetadataMap entity_metadata_map =
+ metadata_batch->TakeAllMetadata();
+ EXPECT_EQ(0U, entity_metadata_map.count(header_storage_key));
+ EXPECT_EQ(0U, entity_metadata_map.count(tab_storage_key));
+ loop.Quit();
+ }));
+ loop.Run();
+ }
}
TEST_F(SessionSyncBridgeTest, ShouldIgnoreRemoteDeletionOfLocalTab) {
diff --git a/chromium/components/sync_sessions/session_sync_test_helper.cc b/chromium/components/sync_sessions/session_sync_test_helper.cc
index 205364e8d16..8d301b723a4 100644
--- a/chromium/components/sync_sessions/session_sync_test_helper.cc
+++ b/chromium/components/sync_sessions/session_sync_test_helper.cc
@@ -88,23 +88,22 @@ void SessionSyncTestHelper::VerifySyncedSession(
}
}
-void SessionSyncTestHelper::BuildTabSpecifics(
+sync_pb::SessionSpecifics SessionSyncTestHelper::BuildTabSpecifics(
const std::string& tag,
SessionID window_id,
- SessionID tab_id,
- sync_pb::SessionSpecifics* tab_base) {
- BuildTabSpecifics(tag, window_id, tab_id, ++max_tab_node_id_, tab_base);
+ SessionID tab_id) {
+ return BuildTabSpecifics(tag, window_id, tab_id, ++max_tab_node_id_);
}
-void SessionSyncTestHelper::BuildTabSpecifics(
+sync_pb::SessionSpecifics SessionSyncTestHelper::BuildTabSpecifics(
const std::string& tag,
SessionID window_id,
SessionID tab_id,
- int tab_node_id,
- sync_pb::SessionSpecifics* tab_base) {
- tab_base->set_session_tag(tag);
- tab_base->set_tab_node_id(tab_node_id);
- sync_pb::SessionTab* tab = tab_base->mutable_tab();
+ int tab_node_id) {
+ sync_pb::SessionSpecifics specifics;
+ specifics.set_session_tag(tag);
+ specifics.set_tab_node_id(tab_node_id);
+ sync_pb::SessionTab* tab = specifics.mutable_tab();
tab->set_tab_id(tab_id.id());
tab->set_tab_visual_index(1);
tab->set_current_navigation_index(0);
@@ -115,6 +114,7 @@ void SessionSyncTestHelper::BuildTabSpecifics(
navigation->set_referrer(kReferrer);
navigation->set_title(kTitle);
navigation->set_page_transition(sync_pb::SyncEnums_PageTransition_TYPED);
+ return specifics;
}
void SessionSyncTestHelper::Reset() {
@@ -125,19 +125,19 @@ sync_pb::SessionSpecifics SessionSyncTestHelper::BuildForeignSession(
const std::string& tag,
const std::vector<SessionID>& tab_list,
std::vector<sync_pb::SessionSpecifics>* tabs) {
- sync_pb::SessionSpecifics meta;
- BuildSessionSpecifics(tag, &meta);
- AddWindowSpecifics(SessionID::FromSerializedValue(1), tab_list, &meta);
- std::vector<sync_pb::SessionSpecifics> tabs1;
- tabs1.resize(tab_list.size());
- for (size_t i = 0; i < tab_list.size(); ++i) {
- BuildTabSpecifics(tag, SessionID::FromSerializedValue(1), tab_list[i],
- &tabs1[i]);
+ const SessionID window_id = SessionID::FromSerializedValue(1);
+ sync_pb::SessionSpecifics header;
+ BuildSessionSpecifics(tag, &header);
+ AddWindowSpecifics(window_id, tab_list, &header);
+
+ if (tabs) {
+ tabs->clear();
+ for (SessionID tab_id : tab_list) {
+ tabs->push_back(BuildTabSpecifics(tag, window_id, tab_id));
+ }
}
- if (tabs)
- tabs->swap(tabs1);
- return meta;
+ return header;
}
} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/session_sync_test_helper.h b/chromium/components/sync_sessions/session_sync_test_helper.h
index 97360aafa22..e5068c3dc64 100644
--- a/chromium/components/sync_sessions/session_sync_test_helper.h
+++ b/chromium/components/sync_sessions/session_sync_test_helper.h
@@ -38,18 +38,16 @@ class SessionSyncTestHelper {
// Build a SessionSpecifics object with a tab and sample data. Uses a
// monotonically increasing variable to generate tab_node_ids and avoid
// conflicts.
- void BuildTabSpecifics(const std::string& tag,
- SessionID window_id,
- SessionID tab_id,
- sync_pb::SessionSpecifics* tab_base);
+ sync_pb::SessionSpecifics BuildTabSpecifics(const std::string& tag,
+ SessionID window_id,
+ SessionID tab_id);
// Overload of BuildTabSpecifics to allow forcing a specific tab_node_id.
// Typically only useful to test reusing tab_node_ids.
- void BuildTabSpecifics(const std::string& tag,
- SessionID window_id,
- SessionID tab_id,
- int tab_node_id,
- sync_pb::SessionSpecifics* tab_base);
+ sync_pb::SessionSpecifics BuildTabSpecifics(const std::string& tag,
+ SessionID window_id,
+ SessionID tab_id,
+ int tab_node_id);
sync_pb::SessionSpecifics BuildForeignSession(
const std::string& tag,