synced_session_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Copyright 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. #include "components/sync_sessions/synced_session.h"
  5. #include <cstddef>
  6. #include <string>
  7. #include "base/strings/string_number_conversions.h"
  8. #include "base/strings/utf_string_conversions.h"
  9. #include "base/time/time.h"
  10. #include "components/sessions/core/serialized_navigation_entry_test_helper.h"
  11. #include "components/sync/base/time.h"
  12. #include "components/sync/protocol/session_specifics.pb.h"
  13. #include "components/sync/protocol/sync_enums.pb.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. #include "ui/base/page_transition_types.h"
  16. #include "url/gurl.h"
  17. namespace sync_sessions {
  18. namespace {
  19. namespace test_data = sessions::test_data;
  20. using sessions::SerializedNavigationEntry;
  21. using sessions::SerializedNavigationEntryTestHelper;
  22. // Create a sync_pb::TabNavigation from the constants above.
  23. sync_pb::TabNavigation MakeSyncDataForTest() {
  24. sync_pb::TabNavigation sync_data;
  25. sync_data.set_virtual_url("http://www.virtual-url.com/");
  26. sync_data.set_referrer("http://www.referrer.com/");
  27. sync_data.set_obsolete_referrer_policy(test_data::kReferrerPolicy);
  28. sync_data.set_correct_referrer_policy(test_data::kReferrerPolicy);
  29. sync_data.set_title(base::UTF16ToUTF8(test_data::kTitle));
  30. sync_data.set_page_transition(
  31. sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME);
  32. sync_data.set_unique_id(test_data::kUniqueID);
  33. sync_data.set_timestamp_msec(syncer::TimeToProtoTime(test_data::kTimestamp));
  34. sync_data.set_redirect_type(sync_pb::SyncEnums::CLIENT_REDIRECT);
  35. sync_data.set_navigation_home_page(true);
  36. sync_data.set_favicon_url("http://virtual-url.com/favicon.ico");
  37. sync_data.set_http_status_code(test_data::kHttpStatusCode);
  38. // The redirect chain only syncs one way.
  39. return sync_data;
  40. }
  41. // Create a SerializedNavigationEntry from a sync_pb::TabNavigation. All its
  42. // fields should match the protocol buffer's if it exists there, and
  43. // should be set to the default value otherwise.
  44. TEST(SyncedSessionTest, SessionNavigationFromSyncData) {
  45. const sync_pb::TabNavigation sync_data = MakeSyncDataForTest();
  46. const SerializedNavigationEntry navigation =
  47. SessionNavigationFromSyncData(test_data::kIndex, sync_data);
  48. EXPECT_EQ(test_data::kIndex, navigation.index());
  49. EXPECT_EQ(sync_data.unique_id(), navigation.unique_id());
  50. EXPECT_EQ(sync_data.referrer(), navigation.referrer_url().spec());
  51. EXPECT_EQ(sync_data.correct_referrer_policy(), navigation.referrer_policy());
  52. EXPECT_EQ(sync_data.virtual_url(), navigation.virtual_url().spec());
  53. EXPECT_EQ(base::UTF8ToUTF16(sync_data.title()), navigation.title());
  54. EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
  55. navigation.transition_type(), test_data::kTransitionType));
  56. EXPECT_FALSE(navigation.has_post_data());
  57. EXPECT_EQ(-1, navigation.post_id());
  58. EXPECT_EQ(GURL(), navigation.original_request_url());
  59. EXPECT_FALSE(navigation.is_overriding_user_agent());
  60. EXPECT_EQ(sync_data.timestamp_msec(),
  61. syncer::TimeToProtoTime(navigation.timestamp()));
  62. EXPECT_EQ(sync_data.favicon_url(), navigation.favicon_url().spec());
  63. EXPECT_EQ(sync_data.http_status_code(), navigation.http_status_code());
  64. // The redirect chain only syncs one way.
  65. }
  66. // Create a SerializedNavigationEntry, then create a sync protocol buffer from
  67. // it. The protocol buffer should have matching fields to the
  68. // SerializedNavigationEntry (when applicable).
  69. TEST(SyncedSessionTest, SessionNavigationToSyncData) {
  70. const SerializedNavigationEntry navigation =
  71. SerializedNavigationEntryTestHelper::CreateNavigationForTest();
  72. const sync_pb::TabNavigation sync_data =
  73. SessionNavigationToSyncData(navigation);
  74. EXPECT_EQ(navigation.virtual_url().spec(), sync_data.virtual_url());
  75. EXPECT_EQ(navigation.referrer_url().spec(), sync_data.referrer());
  76. EXPECT_EQ(navigation.title(), base::UTF8ToUTF16(sync_data.title()));
  77. EXPECT_EQ(sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME,
  78. sync_data.page_transition());
  79. EXPECT_TRUE(sync_data.has_redirect_type());
  80. EXPECT_EQ(navigation.unique_id(), sync_data.unique_id());
  81. EXPECT_EQ(syncer::TimeToProtoTime(navigation.timestamp()),
  82. sync_data.timestamp_msec());
  83. EXPECT_EQ(navigation.favicon_url().spec(), sync_data.favicon_url());
  84. EXPECT_EQ(navigation.http_status_code(), sync_data.http_status_code());
  85. // The proto navigation redirects don't include the final chain entry
  86. // (because it didn't redirect) so the lengths should differ by 1.
  87. ASSERT_EQ(navigation.redirect_chain().size(),
  88. static_cast<size_t>(sync_data.navigation_redirect_size() + 1));
  89. for (auto i = 0; i < sync_data.navigation_redirect_size(); ++i) {
  90. EXPECT_EQ(navigation.redirect_chain()[i].spec(),
  91. sync_data.navigation_redirect(i).url());
  92. }
  93. EXPECT_FALSE(sync_data.has_last_navigation_redirect_url());
  94. EXPECT_FALSE(sync_data.has_replaced_navigation());
  95. }
  96. // Specifically test the |replaced_navigation| field, which should be populated
  97. // when the navigation entry has been replaced by another entry (e.g.
  98. // history.pushState()).
  99. TEST(SyncedSessionTest, SessionNavigationToSyncDataWithReplacedNavigation) {
  100. const GURL kReplacedURL = GURL("http://replaced-url.com");
  101. const int kReplacedTimestampMs = 79;
  102. const ui::PageTransition kReplacedPageTransition =
  103. ui::PAGE_TRANSITION_AUTO_BOOKMARK;
  104. SerializedNavigationEntry navigation =
  105. SerializedNavigationEntryTestHelper::CreateNavigationForTest();
  106. SerializedNavigationEntryTestHelper::SetReplacedEntryData(
  107. {kReplacedURL, syncer::ProtoTimeToTime(kReplacedTimestampMs),
  108. kReplacedPageTransition},
  109. &navigation);
  110. const sync_pb::TabNavigation sync_data =
  111. SessionNavigationToSyncData(navigation);
  112. EXPECT_TRUE(sync_data.has_replaced_navigation());
  113. EXPECT_EQ(kReplacedURL.spec(),
  114. sync_data.replaced_navigation().first_committed_url());
  115. EXPECT_EQ(kReplacedTimestampMs,
  116. sync_data.replaced_navigation().first_timestamp_msec());
  117. EXPECT_EQ(sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK,
  118. sync_data.replaced_navigation().first_page_transition());
  119. }
  120. // Test that the last_navigation_redirect_url is set when needed. This test is
  121. // just like the above, but with a different virtual_url. Create a
  122. // SerializedNavigationEntry, then create a sync protocol buffer from it. The
  123. // protocol buffer should have a last_navigation_redirect_url.
  124. TEST(SyncedSessionTest, SessionNavigationToSyncDataWithLastRedirectUrl) {
  125. SerializedNavigationEntry navigation =
  126. SerializedNavigationEntryTestHelper::CreateNavigationForTest();
  127. SerializedNavigationEntryTestHelper::SetVirtualURL(GURL("http://other.com"),
  128. &navigation);
  129. const sync_pb::TabNavigation sync_data =
  130. SessionNavigationToSyncData(navigation);
  131. EXPECT_TRUE(sync_data.has_last_navigation_redirect_url());
  132. ASSERT_FALSE(navigation.redirect_chain().empty());
  133. EXPECT_EQ(navigation.redirect_chain().back().spec(),
  134. sync_data.last_navigation_redirect_url());
  135. // The redirect chain should be the same as in SessionNavigationToSyncData.
  136. ASSERT_EQ(navigation.redirect_chain().size(),
  137. static_cast<size_t>(sync_data.navigation_redirect_size() + 1));
  138. for (auto i = 0; i < sync_data.navigation_redirect_size(); ++i) {
  139. EXPECT_EQ(navigation.redirect_chain()[i].spec(),
  140. sync_data.navigation_redirect(i).url());
  141. }
  142. }
  143. // Ensure all transition types and qualifiers are converted to/from the sync
  144. // SerializedNavigationEntry representation properly.
  145. TEST(SyncedSessionTest, SessionNavigationToSyncDataWithTransitionTypes) {
  146. SerializedNavigationEntry navigation =
  147. SerializedNavigationEntryTestHelper::CreateNavigationForTest();
  148. for (uint32_t core_type = ui::PAGE_TRANSITION_LINK;
  149. core_type < ui::PAGE_TRANSITION_LAST_CORE; ++core_type) {
  150. // Because qualifier is a uint32_t, left shifting will eventually overflow
  151. // and hit zero again. SERVER_REDIRECT, as the last qualifier and also
  152. // in place of the sign bit, is therefore the last transition before
  153. // breaking.
  154. for (uint32_t qualifier = ui::PAGE_TRANSITION_FORWARD_BACK; qualifier != 0;
  155. qualifier <<= 1) {
  156. if (qualifier == static_cast<uint32_t>(ui::PAGE_TRANSITION_FROM_API)) {
  157. continue; // We don't sync PAGE_TRANSITION_FROM_API.
  158. }
  159. ui::PageTransition transition =
  160. ui::PageTransitionFromInt(core_type | qualifier);
  161. SerializedNavigationEntryTestHelper::SetTransitionType(transition,
  162. &navigation);
  163. const sync_pb::TabNavigation sync_data =
  164. SessionNavigationToSyncData(navigation);
  165. const SerializedNavigationEntry constructed_nav =
  166. SessionNavigationFromSyncData(test_data::kIndex, sync_data);
  167. const ui::PageTransition constructed_transition =
  168. constructed_nav.transition_type();
  169. EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
  170. constructed_transition, transition));
  171. }
  172. }
  173. }
  174. TEST(SyncedSessionTest, SessionNavigationToSyncDataWithLargeFavicon) {
  175. SerializedNavigationEntry navigation =
  176. SerializedNavigationEntryTestHelper::CreateNavigationForTest();
  177. ASSERT_TRUE(SessionNavigationToSyncData(navigation).has_favicon_url());
  178. // The URL size is greater than |kMaxFaviconUrlSizeToSync| so it will be
  179. // omitted.
  180. navigation.set_favicon_url(
  181. GURL(std::string("http://virtual-url.com/") + std::string(2048, 'z')));
  182. const sync_pb::TabNavigation sync_data =
  183. SessionNavigationToSyncData(navigation);
  184. EXPECT_FALSE(sync_data.has_favicon_url());
  185. // The rest of the fields should sync normally, let's verify one of them.
  186. EXPECT_EQ(navigation.virtual_url().spec(), sync_data.virtual_url());
  187. }
  188. // Create a typical SessionTab protocol buffer and set an existing
  189. // SessionTab from it. The data from the protocol buffer should
  190. // clobber the existing data.
  191. TEST(SyncedSessionTest, SetSessionTabFromSyncData) {
  192. sync_pb::SessionTab sync_data;
  193. sync_data.set_tab_id(5);
  194. sync_data.set_window_id(10);
  195. sync_data.set_tab_visual_index(13);
  196. sync_data.set_current_navigation_index(3);
  197. sync_data.set_pinned(true);
  198. sync_data.set_extension_app_id("app_id");
  199. for (int i = 0; i < 5; ++i) {
  200. sync_pb::TabNavigation* navigation = sync_data.add_navigation();
  201. navigation->set_virtual_url("http://foo/" + base::NumberToString(i));
  202. navigation->set_referrer("referrer");
  203. navigation->set_title("title");
  204. navigation->set_page_transition(sync_pb::SyncEnums_PageTransition_TYPED);
  205. }
  206. sessions::SessionTab tab;
  207. tab.window_id = SessionID::FromSerializedValue(100);
  208. tab.tab_id = SessionID::FromSerializedValue(100);
  209. tab.tab_visual_index = 100;
  210. tab.current_navigation_index = 1000;
  211. tab.pinned = false;
  212. tab.extension_app_id = "fake";
  213. tab.user_agent_override.ua_string_override = "fake";
  214. tab.timestamp = base::Time::FromInternalValue(100);
  215. tab.navigations.resize(100);
  216. tab.session_storage_persistent_id = "fake";
  217. SetSessionTabFromSyncData(sync_data, base::Time::FromInternalValue(5u), &tab);
  218. EXPECT_EQ(10, tab.window_id.id());
  219. EXPECT_EQ(5, tab.tab_id.id());
  220. EXPECT_EQ(13, tab.tab_visual_index);
  221. EXPECT_EQ(3, tab.current_navigation_index);
  222. EXPECT_TRUE(tab.pinned);
  223. EXPECT_EQ("app_id", tab.extension_app_id);
  224. EXPECT_TRUE(tab.user_agent_override.ua_string_override.empty());
  225. EXPECT_EQ(5u, tab.timestamp.ToInternalValue());
  226. ASSERT_EQ(5u, tab.navigations.size());
  227. for (int i = 0; i < 5; ++i) {
  228. EXPECT_EQ(i, tab.navigations[i].index());
  229. EXPECT_EQ(GURL("referrer"), tab.navigations[i].referrer_url());
  230. EXPECT_EQ(u"title", tab.navigations[i].title());
  231. EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
  232. tab.navigations[i].transition_type(), ui::PAGE_TRANSITION_TYPED));
  233. EXPECT_EQ(GURL("http://foo/" + base::NumberToString(i)),
  234. tab.navigations[i].virtual_url());
  235. }
  236. EXPECT_TRUE(tab.session_storage_persistent_id.empty());
  237. }
  238. TEST(SyncedSessionTest, SessionTabToSyncData) {
  239. sessions::SessionTab tab;
  240. tab.window_id = SessionID::FromSerializedValue(10);
  241. tab.tab_id = SessionID::FromSerializedValue(5);
  242. tab.tab_visual_index = 13;
  243. tab.current_navigation_index = 3;
  244. tab.pinned = true;
  245. tab.extension_app_id = "app_id";
  246. tab.user_agent_override.ua_string_override = "fake";
  247. tab.timestamp = base::Time::FromInternalValue(100);
  248. for (int i = 0; i < 5; ++i) {
  249. sessions::SerializedNavigationEntry entry =
  250. SerializedNavigationEntryTestHelper::CreateNavigationForTest();
  251. entry.set_virtual_url(GURL("http://foo/" + base::NumberToString(i)));
  252. entry.set_title(base::UTF8ToUTF16("title" + base::NumberToString(i)));
  253. tab.navigations.push_back(entry);
  254. }
  255. tab.session_storage_persistent_id = "fake";
  256. const sync_pb::SessionTab sync_data =
  257. SessionTabToSyncData(tab, /*browser_type=*/absl::nullopt);
  258. EXPECT_EQ(5, sync_data.tab_id());
  259. EXPECT_EQ(10, sync_data.window_id());
  260. EXPECT_EQ(13, sync_data.tab_visual_index());
  261. EXPECT_EQ(3, sync_data.current_navigation_index());
  262. EXPECT_TRUE(sync_data.pinned());
  263. EXPECT_EQ("app_id", sync_data.extension_app_id());
  264. ASSERT_EQ(5, sync_data.navigation_size());
  265. for (int i = 0; i < 5; ++i) {
  266. EXPECT_EQ(tab.navigations[i].virtual_url().spec(),
  267. sync_data.navigation(i).virtual_url());
  268. EXPECT_EQ(base::UTF16ToUTF8(tab.navigations[i].title()),
  269. sync_data.navigation(i).title());
  270. }
  271. EXPECT_FALSE(sync_data.has_favicon());
  272. EXPECT_FALSE(sync_data.has_favicon_type());
  273. EXPECT_FALSE(sync_data.has_favicon_source());
  274. EXPECT_FALSE(sync_data.has_browser_type());
  275. }
  276. TEST(SyncedSessionTest, SessionTabToSyncDataWithBrowserType) {
  277. EXPECT_EQ(sync_pb::SyncEnums_BrowserType_TYPE_TABBED,
  278. SessionTabToSyncData(sessions::SessionTab(),
  279. sync_pb::SyncEnums_BrowserType_TYPE_TABBED)
  280. .browser_type());
  281. EXPECT_EQ(sync_pb::SyncEnums_BrowserType_TYPE_POPUP,
  282. SessionTabToSyncData(sessions::SessionTab(),
  283. sync_pb::SyncEnums_BrowserType_TYPE_POPUP)
  284. .browser_type());
  285. }
  286. } // namespace
  287. } // namespace sync_sessions