blob: dc709c2df74df2338371731c7cac7c1562c00ea2 [file] [log] [blame]
// Copyright 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 "components/sync_sessions/synced_session.h"
#include <cstddef>
#include <string>
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
#include "components/sync/base/time.h"
#include "components/sync/protocol/session_specifics.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
namespace sync_sessions {
namespace {
namespace test_data = sessions::test_data;
using sessions::SerializedNavigationEntry;
using sessions::SerializedNavigationEntryTestHelper;
// Create a sync_pb::TabNavigation from the constants above.
sync_pb::TabNavigation MakeSyncDataForTest() {
sync_pb::TabNavigation sync_data;
sync_data.set_virtual_url(test_data::kVirtualURL.spec());
sync_data.set_referrer(test_data::kReferrerURL.spec());
sync_data.set_obsolete_referrer_policy(test_data::kReferrerPolicy);
sync_data.set_correct_referrer_policy(test_data::kReferrerPolicy);
sync_data.set_title(base::UTF16ToUTF8(test_data::kTitle));
sync_data.set_page_transition(
sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME);
sync_data.set_unique_id(test_data::kUniqueID);
sync_data.set_timestamp_msec(syncer::TimeToProtoTime(test_data::kTimestamp));
sync_data.set_redirect_type(sync_pb::SyncEnums::CLIENT_REDIRECT);
sync_data.set_navigation_home_page(true);
sync_data.set_favicon_url(test_data::kFaviconURL.spec());
sync_data.set_http_status_code(test_data::kHttpStatusCode);
// The redirect chain only syncs one way.
return sync_data;
}
// Create a SerializedNavigationEntry from a sync_pb::TabNavigation. All its
// fields should match the protocol buffer's if it exists there, and
// should be set to the default value otherwise.
TEST(SyncedSessionTest, SessionNavigationFromSyncData) {
const sync_pb::TabNavigation sync_data = MakeSyncDataForTest();
const SerializedNavigationEntry navigation =
SessionNavigationFromSyncData(test_data::kIndex, sync_data);
EXPECT_EQ(test_data::kIndex, navigation.index());
EXPECT_EQ(test_data::kUniqueID, navigation.unique_id());
EXPECT_EQ(test_data::kReferrerURL, navigation.referrer_url());
EXPECT_EQ(test_data::kReferrerPolicy, navigation.referrer_policy());
EXPECT_EQ(test_data::kVirtualURL, navigation.virtual_url());
EXPECT_EQ(test_data::kTitle, navigation.title());
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
navigation.transition_type(), test_data::kTransitionType));
EXPECT_FALSE(navigation.has_post_data());
EXPECT_EQ(-1, navigation.post_id());
EXPECT_EQ(GURL(), navigation.original_request_url());
EXPECT_FALSE(navigation.is_overriding_user_agent());
EXPECT_EQ(test_data::kTimestamp, navigation.timestamp());
EXPECT_EQ(test_data::kFaviconURL, navigation.favicon_url());
EXPECT_EQ(test_data::kHttpStatusCode, navigation.http_status_code());
// The redirect chain only syncs one way.
}
// Create a SerializedNavigationEntry, then create a sync protocol buffer from
// it. The protocol buffer should have matching fields to the
// SerializedNavigationEntry (when applicable).
TEST(SyncedSessionTest, SessionNavigationToSyncData) {
const SerializedNavigationEntry navigation =
SerializedNavigationEntryTestHelper::CreateNavigationForTest();
const sync_pb::TabNavigation sync_data =
SessionNavigationToSyncData(navigation);
EXPECT_EQ(test_data::kVirtualURL.spec(), sync_data.virtual_url());
EXPECT_EQ(test_data::kReferrerURL.spec(), sync_data.referrer());
EXPECT_EQ(test_data::kTitle, base::ASCIIToUTF16(sync_data.title()));
EXPECT_EQ(sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME,
sync_data.page_transition());
EXPECT_TRUE(sync_data.has_redirect_type());
EXPECT_EQ(test_data::kUniqueID, sync_data.unique_id());
EXPECT_EQ(syncer::TimeToProtoTime(test_data::kTimestamp),
sync_data.timestamp_msec());
EXPECT_EQ(test_data::kTimestamp.ToInternalValue(), sync_data.global_id());
EXPECT_EQ(test_data::kFaviconURL.spec(), sync_data.favicon_url());
EXPECT_EQ(test_data::kHttpStatusCode, sync_data.http_status_code());
// The proto navigation redirects don't include the final chain entry
// (because it didn't redirect) so the lengths should differ by 1.
ASSERT_EQ(3, sync_data.navigation_redirect_size() + 1);
EXPECT_EQ(test_data::kRedirectURL0.spec(),
sync_data.navigation_redirect(0).url());
EXPECT_EQ(test_data::kRedirectURL1.spec(),
sync_data.navigation_redirect(1).url());
EXPECT_FALSE(sync_data.has_last_navigation_redirect_url());
EXPECT_FALSE(sync_data.has_replaced_navigation());
}
// Specifically test the |replaced_navigation| field, which should be populated
// when the navigation entry has been replaced by another entry (e.g.
// history.pushState()).
TEST(SyncedSessionTest, SessionNavigationToSyncDataWithReplacedNavigation) {
const GURL kReplacedURL = GURL("http://replaced-url.com");
const int kReplacedTimestampMs = 79;
const ui::PageTransition kReplacedPageTransition =
ui::PAGE_TRANSITION_AUTO_BOOKMARK;
SerializedNavigationEntry navigation =
SerializedNavigationEntryTestHelper::CreateNavigationForTest();
SerializedNavigationEntryTestHelper::SetReplacedEntryData(
{kReplacedURL, syncer::ProtoTimeToTime(kReplacedTimestampMs),
kReplacedPageTransition},
&navigation);
const sync_pb::TabNavigation sync_data =
SessionNavigationToSyncData(navigation);
EXPECT_TRUE(sync_data.has_replaced_navigation());
EXPECT_EQ(kReplacedURL.spec(),
sync_data.replaced_navigation().first_committed_url());
EXPECT_EQ(kReplacedTimestampMs,
sync_data.replaced_navigation().first_timestamp_msec());
EXPECT_EQ(sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK,
sync_data.replaced_navigation().first_page_transition());
}
// Test that the last_navigation_redirect_url is set when needed. This test is
// just like the above, but with a different virtual_url. Create a
// SerializedNavigationEntry, then create a sync protocol buffer from it. The
// protocol buffer should have a last_navigation_redirect_url.
TEST(SyncedSessionTest, SessionNavigationToSyncDataWithLastRedirectUrl) {
SerializedNavigationEntry navigation =
SerializedNavigationEntryTestHelper::CreateNavigationForTest();
SerializedNavigationEntryTestHelper::SetVirtualURL(test_data::kOtherURL,
&navigation);
const sync_pb::TabNavigation sync_data =
SessionNavigationToSyncData(navigation);
EXPECT_TRUE(sync_data.has_last_navigation_redirect_url());
EXPECT_EQ(test_data::kVirtualURL.spec(),
sync_data.last_navigation_redirect_url());
// The redirect chain should be the same as in the above test.
ASSERT_EQ(3, sync_data.navigation_redirect_size() + 1);
EXPECT_EQ(test_data::kRedirectURL0.spec(),
sync_data.navigation_redirect(0).url());
EXPECT_EQ(test_data::kRedirectURL1.spec(),
sync_data.navigation_redirect(1).url());
}
// Ensure all transition types and qualifiers are converted to/from the sync
// SerializedNavigationEntry representation properly.
TEST(SyncedSessionTest, SessionNavigationToSyncDataWithTransitionTypes) {
SerializedNavigationEntry navigation =
SerializedNavigationEntryTestHelper::CreateNavigationForTest();
for (uint32_t core_type = ui::PAGE_TRANSITION_LINK;
core_type < ui::PAGE_TRANSITION_LAST_CORE; ++core_type) {
// Because qualifier is a uint32_t, left shifting will eventually overflow
// and hit zero again. SERVER_REDIRECT, as the last qualifier and also
// in place of the sign bit, is therefore the last transition before
// breaking.
for (uint32_t qualifier = ui::PAGE_TRANSITION_FORWARD_BACK; qualifier != 0;
qualifier <<= 1) {
if (qualifier == static_cast<uint32_t>(ui::PAGE_TRANSITION_FROM_API))
continue; // We don't sync PAGE_TRANSITION_FROM_API.
ui::PageTransition transition =
ui::PageTransitionFromInt(core_type | qualifier);
SerializedNavigationEntryTestHelper::SetTransitionType(transition,
&navigation);
const sync_pb::TabNavigation sync_data =
SessionNavigationToSyncData(navigation);
const SerializedNavigationEntry constructed_nav =
SessionNavigationFromSyncData(test_data::kIndex, sync_data);
const ui::PageTransition constructed_transition =
constructed_nav.transition_type();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
constructed_transition, transition));
}
}
}
// Create a typical SessionTab protocol buffer and set an existing
// SessionTab from it. The data from the protocol buffer should
// clobber the existing data.
TEST(SyncedSessionTest, SetSessionTabFromSyncData) {
sync_pb::SessionTab sync_data;
sync_data.set_tab_id(5);
sync_data.set_window_id(10);
sync_data.set_tab_visual_index(13);
sync_data.set_current_navigation_index(3);
sync_data.set_pinned(true);
sync_data.set_extension_app_id("app_id");
for (int i = 0; i < 5; ++i) {
sync_pb::TabNavigation* navigation = sync_data.add_navigation();
navigation->set_virtual_url("http://foo/" + base::IntToString(i));
navigation->set_referrer("referrer");
navigation->set_title("title");
navigation->set_page_transition(sync_pb::SyncEnums_PageTransition_TYPED);
}
sessions::SessionTab tab;
tab.window_id = SessionID::FromSerializedValue(100);
tab.tab_id = SessionID::FromSerializedValue(100);
tab.tab_visual_index = 100;
tab.current_navigation_index = 1000;
tab.pinned = false;
tab.extension_app_id = "fake";
tab.user_agent_override = "fake";
tab.timestamp = base::Time::FromInternalValue(100);
tab.navigations.resize(100);
tab.session_storage_persistent_id = "fake";
SetSessionTabFromSyncData(sync_data, base::Time::FromInternalValue(5u), &tab);
EXPECT_EQ(10, tab.window_id.id());
EXPECT_EQ(5, tab.tab_id.id());
EXPECT_EQ(13, tab.tab_visual_index);
EXPECT_EQ(3, tab.current_navigation_index);
EXPECT_TRUE(tab.pinned);
EXPECT_EQ("app_id", tab.extension_app_id);
EXPECT_TRUE(tab.user_agent_override.empty());
EXPECT_EQ(5u, tab.timestamp.ToInternalValue());
ASSERT_EQ(5u, tab.navigations.size());
for (int i = 0; i < 5; ++i) {
EXPECT_EQ(i, tab.navigations[i].index());
EXPECT_EQ(GURL("referrer"), tab.navigations[i].referrer_url());
EXPECT_EQ(base::ASCIIToUTF16("title"), tab.navigations[i].title());
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
tab.navigations[i].transition_type(), ui::PAGE_TRANSITION_TYPED));
EXPECT_EQ(GURL("http://foo/" + base::IntToString(i)),
tab.navigations[i].virtual_url());
}
EXPECT_TRUE(tab.session_storage_persistent_id.empty());
}
TEST(SyncedSessionTest, SessionTabToSyncData) {
sessions::SessionTab tab;
tab.window_id = SessionID::FromSerializedValue(10);
tab.tab_id = SessionID::FromSerializedValue(5);
tab.tab_visual_index = 13;
tab.current_navigation_index = 3;
tab.pinned = true;
tab.extension_app_id = "app_id";
tab.user_agent_override = "fake";
tab.timestamp = base::Time::FromInternalValue(100);
for (int i = 0; i < 5; ++i) {
tab.navigations.push_back(
SerializedNavigationEntryTestHelper::CreateNavigation(
"http://foo/" + base::IntToString(i), "title"));
}
tab.session_storage_persistent_id = "fake";
const sync_pb::SessionTab sync_data = SessionTabToSyncData(tab);
EXPECT_EQ(5, sync_data.tab_id());
EXPECT_EQ(10, sync_data.window_id());
EXPECT_EQ(13, sync_data.tab_visual_index());
EXPECT_EQ(3, sync_data.current_navigation_index());
EXPECT_TRUE(sync_data.pinned());
EXPECT_EQ("app_id", sync_data.extension_app_id());
ASSERT_EQ(5, sync_data.navigation_size());
for (int i = 0; i < 5; ++i) {
EXPECT_EQ(tab.navigations[i].virtual_url().spec(),
sync_data.navigation(i).virtual_url());
EXPECT_EQ(base::UTF16ToUTF8(tab.navigations[i].title()),
sync_data.navigation(i).title());
}
EXPECT_FALSE(sync_data.has_favicon());
EXPECT_FALSE(sync_data.has_favicon_type());
EXPECT_FALSE(sync_data.has_favicon_source());
}
} // namespace
} // namespace sync_sessions