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