1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h" 6 7 #include "base/rand_util.h" 8 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/stringprintf.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "chrome/browser/sync/open_tabs_ui_delegate.h" 12 #include "chrome/browser/sync/sessions/sessions_sync_manager.h" 13 #include "sync/api/attachments/attachment_id.h" 14 #include "sync/api/attachments/attachment_service_proxy_for_test.h" 15 #include "sync/protocol/session_specifics.pb.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 namespace { 19 20 const char kBaseSessionTag[] = "session_tag"; 21 const char kBaseSessionName[] = "session_name"; 22 const char kBaseTabUrl[] = "http://foo/?"; 23 const char kTabTitleFormat[] = "session=%d;window=%d;tab=%d"; 24 25 struct TitleTimestampPair { 26 base::string16 title; 27 base::Time timestamp; 28 }; 29 30 bool SortTabTimesByRecency(const TitleTimestampPair& t1, 31 const TitleTimestampPair& t2) { 32 return t1.timestamp > t2.timestamp; 33 } 34 35 int CreateUniqueID() { 36 static int s_id = 0; 37 ++s_id; 38 return s_id; 39 } 40 41 std::string ToSessionTag(SessionID::id_type session_id) { 42 return std::string(kBaseSessionTag + base::IntToString(session_id)); 43 } 44 45 std::string ToSessionName(SessionID::id_type session_id) { 46 return std::string(kBaseSessionName + base::IntToString(session_id)); 47 } 48 49 std::string ToTabTitle(SessionID::id_type session_id, 50 SessionID::id_type window_id, 51 SessionID::id_type tab_id) { 52 return base::StringPrintf(kTabTitleFormat, session_id, window_id, tab_id); 53 } 54 55 std::string ToTabUrl(SessionID::id_type session_id, 56 SessionID::id_type window_id, 57 SessionID::id_type tab_id) { 58 return std::string(kBaseTabUrl + ToTabTitle(session_id, window_id, tab_id)); 59 } 60 61 } // namespace 62 63 struct RecentTabsBuilderTestHelper::TabInfo { 64 TabInfo() : id(0) {} 65 SessionID::id_type id; 66 base::Time timestamp; 67 base::string16 title; 68 }; 69 struct RecentTabsBuilderTestHelper::WindowInfo { 70 WindowInfo() : id(0) {} 71 ~WindowInfo() {} 72 SessionID::id_type id; 73 std::vector<TabInfo> tabs; 74 }; 75 struct RecentTabsBuilderTestHelper::SessionInfo { 76 SessionInfo() : id(0) {} 77 ~SessionInfo() {} 78 SessionID::id_type id; 79 std::vector<WindowInfo> windows; 80 }; 81 82 RecentTabsBuilderTestHelper::RecentTabsBuilderTestHelper() 83 : max_tab_node_id_(0) { 84 start_time_ = base::Time::Now(); 85 } 86 87 RecentTabsBuilderTestHelper::~RecentTabsBuilderTestHelper() { 88 } 89 90 void RecentTabsBuilderTestHelper::AddSession() { 91 SessionInfo info; 92 info.id = CreateUniqueID(); 93 sessions_.push_back(info); 94 } 95 96 int RecentTabsBuilderTestHelper::GetSessionCount() { 97 return sessions_.size(); 98 } 99 100 SessionID::id_type RecentTabsBuilderTestHelper::GetSessionID( 101 int session_index) { 102 return sessions_[session_index].id; 103 } 104 105 base::Time RecentTabsBuilderTestHelper::GetSessionTimestamp(int session_index) { 106 std::vector<base::Time> timestamps; 107 for (int w = 0; w < GetWindowCount(session_index); ++w) { 108 for (int t = 0; t < GetTabCount(session_index, w); ++t) 109 timestamps.push_back(GetTabTimestamp(session_index, w, t)); 110 } 111 112 if (timestamps.empty()) 113 return base::Time::Now(); 114 115 sort(timestamps.begin(), timestamps.end()); 116 return timestamps[0]; 117 } 118 119 void RecentTabsBuilderTestHelper::AddWindow(int session_index) { 120 WindowInfo window_info; 121 window_info.id = CreateUniqueID(); 122 sessions_[session_index].windows.push_back(window_info); 123 } 124 125 int RecentTabsBuilderTestHelper::GetWindowCount(int session_index) { 126 return sessions_[session_index].windows.size(); 127 } 128 129 SessionID::id_type RecentTabsBuilderTestHelper::GetWindowID(int session_index, 130 int window_index) { 131 return sessions_[session_index].windows[window_index].id; 132 } 133 134 void RecentTabsBuilderTestHelper::AddTab(int session_index, int window_index) { 135 base::Time timestamp = 136 start_time_ + base::TimeDelta::FromMinutes(base::RandUint64()); 137 AddTabWithInfo(session_index, window_index, timestamp, base::string16()); 138 } 139 140 void RecentTabsBuilderTestHelper::AddTabWithInfo(int session_index, 141 int window_index, 142 base::Time timestamp, 143 const base::string16& title) { 144 TabInfo tab_info; 145 tab_info.id = CreateUniqueID(); 146 tab_info.timestamp = timestamp; 147 tab_info.title = title; 148 sessions_[session_index].windows[window_index].tabs.push_back(tab_info); 149 } 150 151 int RecentTabsBuilderTestHelper::GetTabCount(int session_index, 152 int window_index) { 153 return sessions_[session_index].windows[window_index].tabs.size(); 154 } 155 156 SessionID::id_type RecentTabsBuilderTestHelper::GetTabID(int session_index, 157 int window_index, 158 int tab_index) { 159 return sessions_[session_index].windows[window_index].tabs[tab_index].id; 160 } 161 162 base::Time RecentTabsBuilderTestHelper::GetTabTimestamp(int session_index, 163 int window_index, 164 int tab_index) { 165 return sessions_[session_index].windows[window_index] 166 .tabs[tab_index].timestamp; 167 } 168 169 base::string16 RecentTabsBuilderTestHelper::GetTabTitle(int session_index, 170 int window_index, 171 int tab_index) { 172 base::string16 title = 173 sessions_[session_index].windows[window_index].tabs[tab_index].title; 174 if (title.empty()) { 175 title = base::UTF8ToUTF16(ToTabTitle( 176 GetSessionID(session_index), 177 GetWindowID(session_index, window_index), 178 GetTabID(session_index, window_index, tab_index))); 179 } 180 return title; 181 } 182 183 void RecentTabsBuilderTestHelper::ExportToSessionsSyncManager( 184 browser_sync::SessionsSyncManager* manager) { 185 syncer::SyncChangeList changes; 186 for (int s = 0; s < GetSessionCount(); ++s) { 187 sync_pb::EntitySpecifics session_entity; 188 sync_pb::SessionSpecifics* meta = session_entity.mutable_session(); 189 BuildSessionSpecifics(s, meta); 190 for (int w = 0; w < GetWindowCount(s); ++w) { 191 BuildWindowSpecifics(s, w, meta); 192 for (int t = 0; t < GetTabCount(s, w); ++t) { 193 sync_pb::EntitySpecifics entity; 194 sync_pb::SessionSpecifics* tab_base = entity.mutable_session(); 195 BuildTabSpecifics(s, w, t, tab_base); 196 changes.push_back(syncer::SyncChange( 197 FROM_HERE, 198 syncer::SyncChange::ACTION_ADD, 199 syncer::SyncData::CreateRemoteData( 200 tab_base->tab_node_id(), 201 entity, 202 GetTabTimestamp(s, w, t), 203 syncer::AttachmentIdList(), 204 syncer::AttachmentServiceProxyForTest::Create()))); 205 } 206 } 207 changes.push_back(syncer::SyncChange( 208 FROM_HERE, 209 syncer::SyncChange::ACTION_ADD, 210 syncer::SyncData::CreateRemoteData( 211 1, 212 session_entity, 213 GetSessionTimestamp(s), 214 syncer::AttachmentIdList(), 215 syncer::AttachmentServiceProxyForTest::Create()))); 216 } 217 manager->ProcessSyncChanges(FROM_HERE, changes); 218 VerifyExport(manager); 219 } 220 221 void RecentTabsBuilderTestHelper::VerifyExport( 222 browser_sync::OpenTabsUIDelegate* delegate) { 223 // Make sure data is populated correctly in SessionModelAssociator. 224 std::vector<const browser_sync::SyncedSession*> sessions; 225 ASSERT_TRUE(delegate->GetAllForeignSessions(&sessions)); 226 ASSERT_EQ(GetSessionCount(), static_cast<int>(sessions.size())); 227 for (int s = 0; s < GetSessionCount(); ++s) { 228 std::vector<const SessionWindow*> windows; 229 ASSERT_TRUE(delegate->GetForeignSession(ToSessionTag(GetSessionID(s)), 230 &windows)); 231 ASSERT_EQ(GetWindowCount(s), static_cast<int>(windows.size())); 232 for (int w = 0; w < GetWindowCount(s); ++w) 233 ASSERT_EQ(GetTabCount(s, w), static_cast<int>(windows[w]->tabs.size())); 234 } 235 } 236 237 std::vector<base::string16> 238 RecentTabsBuilderTestHelper::GetTabTitlesSortedByRecency() { 239 std::vector<TitleTimestampPair> tabs; 240 for (int s = 0; s < GetSessionCount(); ++s) { 241 for (int w = 0; w < GetWindowCount(s); ++w) { 242 for (int t = 0; t < GetTabCount(s, w); ++t) { 243 TitleTimestampPair pair; 244 pair.title = GetTabTitle(s, w, t); 245 pair.timestamp = GetTabTimestamp(s, w, t); 246 tabs.push_back(pair); 247 } 248 } 249 } 250 sort(tabs.begin(), tabs.end(), SortTabTimesByRecency); 251 252 std::vector<base::string16> titles; 253 for (size_t i = 0; i < tabs.size(); ++i) 254 titles.push_back(tabs[i].title); 255 return titles; 256 } 257 258 void RecentTabsBuilderTestHelper::BuildSessionSpecifics( 259 int session_index, 260 sync_pb::SessionSpecifics* meta) { 261 SessionID::id_type session_id = GetSessionID(session_index); 262 meta->set_session_tag(ToSessionTag(session_id)); 263 sync_pb::SessionHeader* header = meta->mutable_header(); 264 header->set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_CROS); 265 header->set_client_name(ToSessionName(session_id)); 266 } 267 268 void RecentTabsBuilderTestHelper::BuildWindowSpecifics( 269 int session_index, 270 int window_index, 271 sync_pb::SessionSpecifics* meta) { 272 sync_pb::SessionHeader* header = meta->mutable_header(); 273 sync_pb::SessionWindow* window = header->add_window(); 274 SessionID::id_type window_id = GetWindowID(session_index, window_index); 275 window->set_window_id(window_id); 276 window->set_selected_tab_index(0); 277 window->set_browser_type(sync_pb::SessionWindow_BrowserType_TYPE_TABBED); 278 for (int i = 0; i < GetTabCount(session_index, window_index); ++i) 279 window->add_tab(GetTabID(session_index, window_index, i)); 280 } 281 282 void RecentTabsBuilderTestHelper::BuildTabSpecifics( 283 int session_index, 284 int window_index, 285 int tab_index, 286 sync_pb::SessionSpecifics* tab_base) { 287 SessionID::id_type session_id = GetSessionID(session_index); 288 SessionID::id_type window_id = GetWindowID(session_index, window_index); 289 SessionID::id_type tab_id = GetTabID(session_index, window_index, tab_index); 290 291 tab_base->set_session_tag(ToSessionTag(session_id)); 292 tab_base->set_tab_node_id(++max_tab_node_id_); 293 sync_pb::SessionTab* tab = tab_base->mutable_tab(); 294 tab->set_window_id(window_id); 295 tab->set_tab_id(tab_id); 296 tab->set_tab_visual_index(1); 297 tab->set_current_navigation_index(0); 298 tab->set_pinned(true); 299 tab->set_extension_app_id("app_id"); 300 sync_pb::TabNavigation* navigation = tab->add_navigation(); 301 navigation->set_virtual_url(ToTabUrl(session_id, window_id, tab_id)); 302 navigation->set_referrer("referrer"); 303 navigation->set_title(base::UTF16ToUTF8(GetTabTitle( 304 session_index, window_index, tab_index))); 305 navigation->set_page_transition(sync_pb::SyncEnums_PageTransition_TYPED); 306 } 307