• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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 "components/sessions/serialized_navigation_entry.h"
6 
7 #include <cstddef>
8 #include <string>
9 
10 #include "base/basictypes.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/pickle.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/time/time.h"
17 #include "content/public/browser/favicon_status.h"
18 #include "content/public/browser/navigation_entry.h"
19 #include "content/public/common/page_transition_types.h"
20 #include "content/public/common/referrer.h"
21 #include "sync/protocol/session_specifics.pb.h"
22 #include "sync/util/time.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
25 #include "url/gurl.h"
26 
27 namespace sessions {
28 namespace {
29 
30 const int kIndex = 3;
31 const int kUniqueID = 50;
32 const content::Referrer kReferrer =
33     content::Referrer(GURL("http://www.referrer.com"),
34                       blink::WebReferrerPolicyAlways);
35 const GURL kVirtualURL("http://www.virtual-url.com");
36 const base::string16 kTitle = ASCIIToUTF16("title");
37 const content::PageState kPageState =
38     content::PageState::CreateFromEncodedData("page state");
39 const content::PageTransition kTransitionType =
40     static_cast<content::PageTransition>(
41         content::PAGE_TRANSITION_AUTO_SUBFRAME |
42         content::PAGE_TRANSITION_HOME_PAGE |
43         content::PAGE_TRANSITION_CLIENT_REDIRECT);
44 const bool kHasPostData = true;
45 const int64 kPostID = 100;
46 const GURL kOriginalRequestURL("http://www.original-request.com");
47 const bool kIsOverridingUserAgent = true;
48 const base::Time kTimestamp = syncer::ProtoTimeToTime(100);
49 const base::string16 kSearchTerms = ASCIIToUTF16("my search terms");
50 const GURL kFaviconURL("http://virtual-url.com/favicon.ico");
51 const int kHttpStatusCode = 404;
52 
53 const int kPageID = 10;
54 
55 // Create a NavigationEntry from the constants above.
MakeNavigationEntryForTest()56 scoped_ptr<content::NavigationEntry> MakeNavigationEntryForTest() {
57   scoped_ptr<content::NavigationEntry> navigation_entry(
58       content::NavigationEntry::Create());
59   navigation_entry->SetReferrer(kReferrer);
60   navigation_entry->SetVirtualURL(kVirtualURL);
61   navigation_entry->SetTitle(kTitle);
62   navigation_entry->SetPageState(kPageState);
63   navigation_entry->SetTransitionType(kTransitionType);
64   navigation_entry->SetHasPostData(kHasPostData);
65   navigation_entry->SetPostID(kPostID);
66   navigation_entry->SetOriginalRequestURL(kOriginalRequestURL);
67   navigation_entry->SetIsOverridingUserAgent(kIsOverridingUserAgent);
68   navigation_entry->SetTimestamp(kTimestamp);
69   navigation_entry->SetExtraData(kSearchTermsKey, kSearchTerms);
70   navigation_entry->GetFavicon().valid = true;
71   navigation_entry->GetFavicon().url = kFaviconURL;
72   navigation_entry->SetHttpStatusCode(kHttpStatusCode);
73   return navigation_entry.Pass();
74 }
75 
76 // Create a sync_pb::TabNavigation from the constants above.
MakeSyncDataForTest()77 sync_pb::TabNavigation MakeSyncDataForTest() {
78   sync_pb::TabNavigation sync_data;
79   sync_data.set_virtual_url(kVirtualURL.spec());
80   sync_data.set_referrer(kReferrer.url.spec());
81   sync_data.set_title(UTF16ToUTF8(kTitle));
82   sync_data.set_state(kPageState.ToEncodedData());
83   sync_data.set_page_transition(
84       sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME);
85   sync_data.set_unique_id(kUniqueID);
86   sync_data.set_timestamp_msec(syncer::TimeToProtoTime(kTimestamp));
87   sync_data.set_redirect_type(sync_pb::SyncEnums::CLIENT_REDIRECT);
88   sync_data.set_navigation_home_page(true);
89   sync_data.set_search_terms(UTF16ToUTF8(kSearchTerms));
90   sync_data.set_favicon_url(kFaviconURL.spec());
91   sync_data.set_http_status_code(kHttpStatusCode);
92   return sync_data;
93 }
94 
95 // Create a default SerializedNavigationEntry.  All its fields should be
96 // initialized to their respective default values.
TEST(SerializedNavigationEntryTest,DefaultInitializer)97 TEST(SerializedNavigationEntryTest, DefaultInitializer) {
98   const SerializedNavigationEntry navigation;
99   EXPECT_EQ(-1, navigation.index());
100   EXPECT_EQ(0, navigation.unique_id());
101   EXPECT_EQ(GURL(), navigation.referrer().url);
102   EXPECT_EQ(blink::WebReferrerPolicyDefault, navigation.referrer().policy);
103   EXPECT_EQ(GURL(), navigation.virtual_url());
104   EXPECT_TRUE(navigation.title().empty());
105   EXPECT_FALSE(navigation.page_state().IsValid());
106   EXPECT_EQ(content::PAGE_TRANSITION_TYPED, navigation.transition_type());
107   EXPECT_FALSE(navigation.has_post_data());
108   EXPECT_EQ(-1, navigation.post_id());
109   EXPECT_EQ(GURL(), navigation.original_request_url());
110   EXPECT_FALSE(navigation.is_overriding_user_agent());
111   EXPECT_TRUE(navigation.timestamp().is_null());
112   EXPECT_TRUE(navigation.search_terms().empty());
113   EXPECT_FALSE(navigation.favicon_url().is_valid());
114   EXPECT_EQ(0, navigation.http_status_code());
115 }
116 
117 // Create a SerializedNavigationEntry from a NavigationEntry.  All its fields
118 // should match the NavigationEntry's.
TEST(SerializedNavigationEntryTest,FromNavigationEntry)119 TEST(SerializedNavigationEntryTest, FromNavigationEntry) {
120   const scoped_ptr<content::NavigationEntry> navigation_entry(
121       MakeNavigationEntryForTest());
122 
123   const SerializedNavigationEntry& navigation =
124       SerializedNavigationEntry::FromNavigationEntry(kIndex, *navigation_entry);
125 
126   EXPECT_EQ(kIndex, navigation.index());
127 
128   EXPECT_EQ(navigation_entry->GetUniqueID(), navigation.unique_id());
129   EXPECT_EQ(kReferrer.url, navigation.referrer().url);
130   EXPECT_EQ(kReferrer.policy, navigation.referrer().policy);
131   EXPECT_EQ(kVirtualURL, navigation.virtual_url());
132   EXPECT_EQ(kTitle, navigation.title());
133   EXPECT_EQ(kPageState, navigation.page_state());
134   EXPECT_EQ(kTransitionType, navigation.transition_type());
135   EXPECT_EQ(kHasPostData, navigation.has_post_data());
136   EXPECT_EQ(kPostID, navigation.post_id());
137   EXPECT_EQ(kOriginalRequestURL, navigation.original_request_url());
138   EXPECT_EQ(kIsOverridingUserAgent, navigation.is_overriding_user_agent());
139   EXPECT_EQ(kTimestamp, navigation.timestamp());
140   EXPECT_EQ(kFaviconURL, navigation.favicon_url());
141   EXPECT_EQ(kHttpStatusCode, navigation.http_status_code());
142 }
143 
144 // Create a SerializedNavigationEntry from a sync_pb::TabNavigation.  All its
145 // fields should match the protocol buffer's if it exists there, and
146 // sbould be set to the default value otherwise.
TEST(SerializedNavigationEntryTest,FromSyncData)147 TEST(SerializedNavigationEntryTest, FromSyncData) {
148   const sync_pb::TabNavigation sync_data = MakeSyncDataForTest();
149 
150   const SerializedNavigationEntry& navigation =
151       SerializedNavigationEntry::FromSyncData(kIndex, sync_data);
152 
153   EXPECT_EQ(kIndex, navigation.index());
154   EXPECT_EQ(kUniqueID, navigation.unique_id());
155   EXPECT_EQ(kReferrer.url, navigation.referrer().url);
156   EXPECT_EQ(blink::WebReferrerPolicyDefault, navigation.referrer().policy);
157   EXPECT_EQ(kVirtualURL, navigation.virtual_url());
158   EXPECT_EQ(kTitle, navigation.title());
159   EXPECT_EQ(kPageState, navigation.page_state());
160   EXPECT_EQ(kTransitionType, navigation.transition_type());
161   EXPECT_FALSE(navigation.has_post_data());
162   EXPECT_EQ(-1, navigation.post_id());
163   EXPECT_EQ(GURL(), navigation.original_request_url());
164   EXPECT_FALSE(navigation.is_overriding_user_agent());
165   EXPECT_TRUE(navigation.timestamp().is_null());
166   EXPECT_EQ(kSearchTerms, navigation.search_terms());
167   EXPECT_EQ(kFaviconURL, navigation.favicon_url());
168   EXPECT_EQ(kHttpStatusCode, navigation.http_status_code());
169 }
170 
171 // Create a SerializedNavigationEntry, pickle it, then create another one by
172 // unpickling.  The new one should match the old one except for fields
173 // that aren't pickled, which should be set to default values.
TEST(SerializedNavigationEntryTest,Pickle)174 TEST(SerializedNavigationEntryTest, Pickle) {
175   const SerializedNavigationEntry& old_navigation =
176       SerializedNavigationEntry::FromNavigationEntry(
177           kIndex, *MakeNavigationEntryForTest());
178 
179   Pickle pickle;
180   old_navigation.WriteToPickle(30000, &pickle);
181 
182   SerializedNavigationEntry new_navigation;
183   PickleIterator pickle_iterator(pickle);
184   EXPECT_TRUE(new_navigation.ReadFromPickle(&pickle_iterator));
185 
186   EXPECT_EQ(kIndex, new_navigation.index());
187 
188   EXPECT_EQ(0, new_navigation.unique_id());
189   EXPECT_EQ(kReferrer.url, new_navigation.referrer().url);
190   EXPECT_EQ(kReferrer.policy, new_navigation.referrer().policy);
191   EXPECT_EQ(kVirtualURL, new_navigation.virtual_url());
192   EXPECT_EQ(kTitle, new_navigation.title());
193   EXPECT_FALSE(new_navigation.page_state().IsValid());
194   EXPECT_EQ(kTransitionType, new_navigation.transition_type());
195   EXPECT_EQ(kHasPostData, new_navigation.has_post_data());
196   EXPECT_EQ(-1, new_navigation.post_id());
197   EXPECT_EQ(kOriginalRequestURL, new_navigation.original_request_url());
198   EXPECT_EQ(kIsOverridingUserAgent, new_navigation.is_overriding_user_agent());
199   EXPECT_EQ(kTimestamp, new_navigation.timestamp());
200   EXPECT_EQ(kSearchTerms, new_navigation.search_terms());
201   EXPECT_EQ(kHttpStatusCode, new_navigation.http_status_code());
202 }
203 
204 // Create a NavigationEntry, then create another one by converting to
205 // a SerializedNavigationEntry and back.  The new one should match the old one
206 // except for fields that aren't preserved, which should be set to
207 // expected values.
TEST(SerializedNavigationEntryTest,ToNavigationEntry)208 TEST(SerializedNavigationEntryTest, ToNavigationEntry) {
209   const scoped_ptr<content::NavigationEntry> old_navigation_entry(
210       MakeNavigationEntryForTest());
211 
212   const SerializedNavigationEntry& navigation =
213       SerializedNavigationEntry::FromNavigationEntry(kIndex,
214                                                      *old_navigation_entry);
215 
216   const scoped_ptr<content::NavigationEntry> new_navigation_entry(
217       navigation.ToNavigationEntry(kPageID, NULL));
218 
219   EXPECT_EQ(kReferrer.url, new_navigation_entry->GetReferrer().url);
220   EXPECT_EQ(kReferrer.policy, new_navigation_entry->GetReferrer().policy);
221   EXPECT_EQ(kVirtualURL, new_navigation_entry->GetVirtualURL());
222   EXPECT_EQ(kTitle, new_navigation_entry->GetTitle());
223   EXPECT_EQ(kPageState, new_navigation_entry->GetPageState());
224   EXPECT_EQ(kPageID, new_navigation_entry->GetPageID());
225   EXPECT_EQ(content::PAGE_TRANSITION_RELOAD,
226             new_navigation_entry->GetTransitionType());
227   EXPECT_EQ(kHasPostData, new_navigation_entry->GetHasPostData());
228   EXPECT_EQ(kPostID, new_navigation_entry->GetPostID());
229   EXPECT_EQ(kOriginalRequestURL,
230             new_navigation_entry->GetOriginalRequestURL());
231   EXPECT_EQ(kIsOverridingUserAgent,
232             new_navigation_entry->GetIsOverridingUserAgent());
233   base::string16 search_terms;
234   new_navigation_entry->GetExtraData(kSearchTermsKey, &search_terms);
235   EXPECT_EQ(kSearchTerms, search_terms);
236   EXPECT_EQ(kHttpStatusCode, new_navigation_entry->GetHttpStatusCode());
237 }
238 
239 // Create a NavigationEntry, convert it to a SerializedNavigationEntry, then
240 // create a sync protocol buffer from it.  The protocol buffer should
241 // have matching fields to the NavigationEntry (when applicable).
TEST(SerializedNavigationEntryTest,ToSyncData)242 TEST(SerializedNavigationEntryTest, ToSyncData) {
243   const scoped_ptr<content::NavigationEntry> navigation_entry(
244       MakeNavigationEntryForTest());
245 
246   const SerializedNavigationEntry& navigation =
247       SerializedNavigationEntry::FromNavigationEntry(kIndex, *navigation_entry);
248 
249   const sync_pb::TabNavigation sync_data = navigation.ToSyncData();
250 
251   EXPECT_EQ(kVirtualURL.spec(), sync_data.virtual_url());
252   EXPECT_EQ(kReferrer.url.spec(), sync_data.referrer());
253   EXPECT_EQ(kTitle, ASCIIToUTF16(sync_data.title()));
254   EXPECT_TRUE(sync_data.state().empty());
255   EXPECT_EQ(sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME,
256             sync_data.page_transition());
257   EXPECT_TRUE(sync_data.has_redirect_type());
258   EXPECT_EQ(navigation_entry->GetUniqueID(), sync_data.unique_id());
259   EXPECT_EQ(syncer::TimeToProtoTime(kTimestamp), sync_data.timestamp_msec());
260   EXPECT_EQ(kTimestamp.ToInternalValue(), sync_data.global_id());
261   EXPECT_EQ(kFaviconURL.spec(), sync_data.favicon_url());
262   EXPECT_EQ(kHttpStatusCode, sync_data.http_status_code());
263 }
264 
265 // Ensure all transition types and qualifiers are converted to/from the sync
266 // SerializedNavigationEntry representation properly.
TEST(SerializedNavigationEntryTest,TransitionTypes)267 TEST(SerializedNavigationEntryTest, TransitionTypes) {
268   scoped_ptr<content::NavigationEntry> navigation_entry(
269       MakeNavigationEntryForTest());
270   for (uint32 core_type = content::PAGE_TRANSITION_LINK;
271        core_type != content::PAGE_TRANSITION_LAST_CORE; ++core_type) {
272     // Because qualifier is a uint32, left shifting will eventually overflow
273     // and hit zero again. SERVER_REDIRECT, as the last qualifier and also
274     // in place of the sign bit, is therefore the last transition before
275     // breaking.
276     for (uint32 qualifier = content::PAGE_TRANSITION_FORWARD_BACK;
277          qualifier != 0; qualifier <<= 1) {
278       if (qualifier == 0x08000000)
279         continue;  // 0x08000000 is not a valid qualifier.
280       content::PageTransition transition =
281           static_cast<content::PageTransition>(core_type | qualifier);
282 
283       navigation_entry->SetTransitionType(transition);
284       const SerializedNavigationEntry& navigation =
285           SerializedNavigationEntry::FromNavigationEntry(kIndex,
286                                                          *navigation_entry);
287       const sync_pb::TabNavigation& sync_data = navigation.ToSyncData();
288       const SerializedNavigationEntry& constructed_nav =
289           SerializedNavigationEntry::FromSyncData(kIndex, sync_data);
290       const content::PageTransition constructed_transition =
291           constructed_nav.transition_type();
292 
293       EXPECT_EQ(transition, constructed_transition);
294     }
295   }
296 }
297 
298 }  // namespace
299 }  // namespace sessions
300