| // Copyright (c) 2012 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 "chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h" |
| |
| #include <stddef.h> |
| |
| #include <algorithm> |
| #include <string> |
| |
| #include "base/rand_util.h" |
| #include "base/run_loop.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "components/sync/base/hash_util.h" |
| #include "components/sync/engine/model_type_processor.h" |
| #include "components/sync/engine/non_blocking_sync_common.h" |
| #include "components/sync/model/entity_data.h" |
| #include "components/sync/model_impl/in_memory_metadata_change_list.h" |
| #include "components/sync/protocol/session_specifics.pb.h" |
| #include "components/sync_sessions/open_tabs_ui_delegate.h" |
| #include "components/sync_sessions/session_store.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| const char kBaseSessionTag[] = "session_tag"; |
| const char kBaseSessionName[] = "session_name"; |
| const char kBaseTabUrl[] = "http://foo/?"; |
| const char kTabTitleFormat[] = "session=%d;window=%d;tab=%d"; |
| const uint64_t kMaxMinutesRange = 1000; |
| |
| struct TitleTimestampPair { |
| base::string16 title; |
| base::Time timestamp; |
| }; |
| |
| bool SortTabTimesByRecency(const TitleTimestampPair& t1, |
| const TitleTimestampPair& t2) { |
| return t1.timestamp > t2.timestamp; |
| } |
| |
| std::string ToSessionTag(SessionID session_id) { |
| return std::string(kBaseSessionTag + base::NumberToString(session_id.id())); |
| } |
| |
| std::string ToSessionName(SessionID session_id) { |
| return std::string(kBaseSessionName + base::NumberToString(session_id.id())); |
| } |
| |
| std::string ToTabTitle(SessionID session_id, |
| SessionID window_id, |
| SessionID tab_id) { |
| return base::StringPrintf(kTabTitleFormat, session_id.id(), window_id.id(), |
| tab_id.id()); |
| } |
| |
| std::string ToTabUrl(SessionID session_id, |
| SessionID window_id, |
| SessionID tab_id) { |
| return std::string(kBaseTabUrl + ToTabTitle(session_id, window_id, tab_id)); |
| } |
| |
| } // namespace |
| |
| struct RecentTabsBuilderTestHelper::TabInfo { |
| TabInfo() : id(SessionID::InvalidValue()) {} |
| SessionID id; |
| base::Time timestamp; |
| base::string16 title; |
| }; |
| struct RecentTabsBuilderTestHelper::WindowInfo { |
| WindowInfo() : id(SessionID::InvalidValue()) {} |
| ~WindowInfo() {} |
| SessionID id; |
| std::vector<TabInfo> tabs; |
| }; |
| struct RecentTabsBuilderTestHelper::SessionInfo { |
| SessionInfo() : id(SessionID::InvalidValue()) {} |
| ~SessionInfo() {} |
| SessionID id; |
| std::vector<WindowInfo> windows; |
| }; |
| |
| RecentTabsBuilderTestHelper::RecentTabsBuilderTestHelper() { |
| start_time_ = base::Time::Now(); |
| } |
| |
| RecentTabsBuilderTestHelper::~RecentTabsBuilderTestHelper() { |
| } |
| |
| void RecentTabsBuilderTestHelper::AddSession() { |
| SessionInfo info; |
| info.id = SessionID::NewUnique(); |
| sessions_.push_back(info); |
| } |
| |
| int RecentTabsBuilderTestHelper::GetSessionCount() { |
| return sessions_.size(); |
| } |
| |
| SessionID RecentTabsBuilderTestHelper::GetSessionID(int session_index) { |
| return sessions_[session_index].id; |
| } |
| |
| base::Time RecentTabsBuilderTestHelper::GetSessionTimestamp(int session_index) { |
| std::vector<base::Time> timestamps; |
| for (int w = 0; w < GetWindowCount(session_index); ++w) { |
| for (int t = 0; t < GetTabCount(session_index, w); ++t) |
| timestamps.push_back(GetTabTimestamp(session_index, w, t)); |
| } |
| |
| if (timestamps.empty()) |
| return base::Time::Now(); |
| |
| sort(timestamps.begin(), timestamps.end()); |
| return timestamps[0]; |
| } |
| |
| void RecentTabsBuilderTestHelper::AddWindow(int session_index) { |
| WindowInfo window_info; |
| window_info.id = SessionID::NewUnique(); |
| sessions_[session_index].windows.push_back(window_info); |
| } |
| |
| int RecentTabsBuilderTestHelper::GetWindowCount(int session_index) { |
| return sessions_[session_index].windows.size(); |
| } |
| |
| SessionID RecentTabsBuilderTestHelper::GetWindowID(int session_index, |
| int window_index) { |
| return sessions_[session_index].windows[window_index].id; |
| } |
| |
| void RecentTabsBuilderTestHelper::AddTab(int session_index, int window_index) { |
| base::Time timestamp = |
| start_time_ + |
| base::TimeDelta::FromMinutes(base::RandGenerator(kMaxMinutesRange)); |
| AddTabWithInfo(session_index, window_index, timestamp, base::string16()); |
| } |
| |
| void RecentTabsBuilderTestHelper::AddTabWithInfo(int session_index, |
| int window_index, |
| base::Time timestamp, |
| const base::string16& title) { |
| TabInfo tab_info; |
| tab_info.id = SessionID::NewUnique(); |
| tab_info.timestamp = timestamp; |
| tab_info.title = title; |
| sessions_[session_index].windows[window_index].tabs.push_back(tab_info); |
| } |
| |
| int RecentTabsBuilderTestHelper::GetTabCount(int session_index, |
| int window_index) { |
| return sessions_[session_index].windows[window_index].tabs.size(); |
| } |
| |
| SessionID RecentTabsBuilderTestHelper::GetTabID(int session_index, |
| int window_index, |
| int tab_index) { |
| return sessions_[session_index].windows[window_index].tabs[tab_index].id; |
| } |
| |
| base::Time RecentTabsBuilderTestHelper::GetTabTimestamp(int session_index, |
| int window_index, |
| int tab_index) { |
| return sessions_[session_index].windows[window_index] |
| .tabs[tab_index].timestamp; |
| } |
| |
| base::string16 RecentTabsBuilderTestHelper::GetTabTitle(int session_index, |
| int window_index, |
| int tab_index) { |
| base::string16 title = |
| sessions_[session_index].windows[window_index].tabs[tab_index].title; |
| if (title.empty()) { |
| title = base::UTF8ToUTF16(ToTabTitle( |
| GetSessionID(session_index), |
| GetWindowID(session_index, window_index), |
| GetTabID(session_index, window_index, tab_index))); |
| } |
| return title; |
| } |
| |
| void RecentTabsBuilderTestHelper::ExportToSessionSync( |
| syncer::ModelTypeProcessor* processor) { |
| syncer::UpdateResponseDataList updates; |
| |
| for (int s = 0; s < GetSessionCount(); ++s) { |
| sync_pb::SessionSpecifics header_specifics = BuildHeaderSpecifics(s); |
| for (int w = 0; w < GetWindowCount(s); ++w) { |
| AddWindowToHeaderSpecifics(s, w, &header_specifics); |
| for (int t = 0; t < GetTabCount(s, w); ++t) { |
| updates.push_back(BuildUpdateResponseData(BuildTabSpecifics(s, w, t), |
| GetTabTimestamp(s, w, t))); |
| } |
| } |
| |
| updates.push_back( |
| BuildUpdateResponseData(header_specifics, GetSessionTimestamp(s))); |
| } |
| |
| sync_pb::ModelTypeState model_type_state; |
| model_type_state.set_initial_sync_done(true); |
| processor->OnUpdateReceived(model_type_state, std::move(updates)); |
| // ClientTagBasedModelTypeProcessor uses ModelTypeProcessorProxy during |
| // activation, which involves task posting for receiving updates. |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void RecentTabsBuilderTestHelper::VerifyExport( |
| sync_sessions::OpenTabsUIDelegate* delegate) { |
| DCHECK(delegate); |
| // Make sure data is populated correctly in SessionModelAssociator. |
| std::vector<const sync_sessions::SyncedSession*> sessions; |
| ASSERT_TRUE(delegate->GetAllForeignSessions(&sessions)); |
| ASSERT_EQ(GetSessionCount(), static_cast<int>(sessions.size())); |
| for (int s = 0; s < GetSessionCount(); ++s) { |
| std::vector<const sessions::SessionWindow*> windows; |
| ASSERT_TRUE(delegate->GetForeignSession(ToSessionTag(GetSessionID(s)), |
| &windows)); |
| ASSERT_EQ(GetWindowCount(s), static_cast<int>(windows.size())); |
| for (int w = 0; w < GetWindowCount(s); ++w) |
| ASSERT_EQ(GetTabCount(s, w), static_cast<int>(windows[w]->tabs.size())); |
| } |
| } |
| |
| std::vector<base::string16> |
| RecentTabsBuilderTestHelper::GetTabTitlesSortedByRecency() { |
| std::vector<TitleTimestampPair> tabs; |
| for (int s = 0; s < GetSessionCount(); ++s) { |
| for (int w = 0; w < GetWindowCount(s); ++w) { |
| for (int t = 0; t < GetTabCount(s, w); ++t) { |
| TitleTimestampPair pair; |
| pair.title = GetTabTitle(s, w, t); |
| pair.timestamp = GetTabTimestamp(s, w, t); |
| tabs.push_back(pair); |
| } |
| } |
| } |
| sort(tabs.begin(), tabs.end(), SortTabTimesByRecency); |
| |
| std::vector<base::string16> titles; |
| for (size_t i = 0; i < tabs.size(); ++i) |
| titles.push_back(tabs[i].title); |
| return titles; |
| } |
| |
| sync_pb::SessionSpecifics RecentTabsBuilderTestHelper::BuildHeaderSpecifics( |
| int session_index) { |
| sync_pb::SessionSpecifics specifics; |
| SessionID session_id = GetSessionID(session_index); |
| specifics.set_session_tag(ToSessionTag(session_id)); |
| sync_pb::SessionHeader* header = specifics.mutable_header(); |
| header->set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_CROS); |
| header->set_client_name(ToSessionName(session_id)); |
| return specifics; |
| } |
| |
| void RecentTabsBuilderTestHelper::AddWindowToHeaderSpecifics( |
| int session_index, |
| int window_index, |
| sync_pb::SessionSpecifics* specifics) { |
| sync_pb::SessionWindow* window = specifics->mutable_header()->add_window(); |
| SessionID window_id = GetWindowID(session_index, window_index); |
| window->set_window_id(window_id.id()); |
| window->set_selected_tab_index(0); |
| window->set_browser_type(sync_pb::SessionWindow_BrowserType_TYPE_TABBED); |
| for (int i = 0; i < GetTabCount(session_index, window_index); ++i) |
| window->add_tab(GetTabID(session_index, window_index, i).id()); |
| } |
| |
| sync_pb::SessionSpecifics RecentTabsBuilderTestHelper::BuildTabSpecifics( |
| int session_index, |
| int window_index, |
| int tab_index) { |
| sync_pb::SessionSpecifics specifics; |
| |
| SessionID session_id = GetSessionID(session_index); |
| SessionID window_id = GetWindowID(session_index, window_index); |
| SessionID tab_id = GetTabID(session_index, window_index, tab_index); |
| |
| specifics.set_session_tag(ToSessionTag(session_id)); |
| specifics.set_tab_node_id(++max_tab_node_id_); |
| sync_pb::SessionTab* tab = specifics.mutable_tab(); |
| tab->set_window_id(window_id.id()); |
| tab->set_tab_id(tab_id.id()); |
| tab->set_tab_visual_index(1); |
| tab->set_current_navigation_index(0); |
| tab->set_pinned(true); |
| tab->set_extension_app_id("app_id"); |
| sync_pb::TabNavigation* navigation = tab->add_navigation(); |
| navigation->set_virtual_url(ToTabUrl(session_id, window_id, tab_id)); |
| navigation->set_referrer("referrer"); |
| navigation->set_title(base::UTF16ToUTF8(GetTabTitle( |
| session_index, window_index, tab_index))); |
| navigation->set_page_transition(sync_pb::SyncEnums_PageTransition_TYPED); |
| |
| return specifics; |
| } |
| |
| std::unique_ptr<syncer::UpdateResponseData> |
| RecentTabsBuilderTestHelper::BuildUpdateResponseData( |
| const sync_pb::SessionSpecifics& specifics, |
| base::Time timestamp) { |
| auto entity = std::make_unique<syncer::EntityData>(); |
| *entity->specifics.mutable_session() = specifics; |
| entity->creation_time = timestamp; |
| entity->modification_time = timestamp; |
| entity->client_tag_hash = syncer::GenerateSyncableHash( |
| syncer::SESSIONS, sync_sessions::SessionStore::GetClientTag(specifics)); |
| entity->id = entity->client_tag_hash; |
| |
| auto update = std::make_unique<syncer::UpdateResponseData>(); |
| update->entity = std::move(entity); |
| update->response_version = ++next_response_version_; |
| return update; |
| } |