OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/web/navigation/crw_session_entry.h" | 5 #import "ios/web/navigation/crw_session_entry.h" |
6 | 6 |
7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #import "base/mac/scoped_nsobject.h" | 12 #import "base/mac/scoped_nsobject.h" |
13 #include "base/strings/sys_string_conversions.h" | 13 #include "base/strings/sys_string_conversions.h" |
14 #import "ios/testing/ocmock_complex_type_helper.h" | 14 #import "ios/testing/ocmock_complex_type_helper.h" |
15 #import "ios/web/navigation/navigation_item_impl.h" | 15 #import "ios/web/navigation/navigation_item_impl.h" |
16 #include "ios/web/public/referrer.h" | 16 #include "ios/web/public/referrer.h" |
17 #import "net/base/mac/url_conversions.h" | 17 #import "net/base/mac/url_conversions.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
19 #import "testing/gtest_mac.h" | 19 #import "testing/gtest_mac.h" |
20 #include "testing/platform_test.h" | 20 #include "testing/platform_test.h" |
21 #import "third_party/ocmock/OCMock/OCMock.h" | 21 #import "third_party/ocmock/OCMock/OCMock.h" |
22 #include "third_party/ocmock/gtest_support.h" | 22 #include "third_party/ocmock/gtest_support.h" |
23 #include "ui/base/page_transition_types.h" | 23 #include "ui/base/page_transition_types.h" |
24 | 24 |
25 @interface CRWSessionEntry (ExposedForTesting) | |
26 + (web::PageScrollState)pageStateFromDictionary:(NSDictionary*)dictionary; | |
27 + (NSDictionary*)dictionaryFromPageDisplayState: | |
28 (const web::PageDisplayState&)displayState; | |
29 @end | |
30 | |
31 class CRWSessionEntryTest : public PlatformTest { | 25 class CRWSessionEntryTest : public PlatformTest { |
32 public: | 26 public: |
33 static void expectEqualSessionEntries(CRWSessionEntry* entry1, | 27 static void expectEqualSessionEntries(CRWSessionEntry* entry1, |
34 CRWSessionEntry* entry2, | 28 CRWSessionEntry* entry2, |
35 ui::PageTransition transition); | 29 ui::PageTransition transition); |
36 | 30 |
37 protected: | 31 protected: |
38 void SetUp() override { | 32 void SetUp() override { |
39 GURL url("http://init.test"); | 33 GURL url("http://init.test"); |
40 ui::PageTransition transition = | 34 ui::PageTransition transition = |
41 ui::PAGE_TRANSITION_AUTO_BOOKMARK; | 35 ui::PAGE_TRANSITION_AUTO_BOOKMARK; |
42 std::unique_ptr<web::NavigationItemImpl> item( | 36 std::unique_ptr<web::NavigationItemImpl> item( |
43 new web::NavigationItemImpl()); | 37 new web::NavigationItemImpl()); |
44 item->SetOriginalRequestURL(url); | 38 item->SetOriginalRequestURL(url); |
45 item->SetURL(url); | 39 item->SetURL(url); |
46 item->SetTransitionType(transition); | 40 item->SetTransitionType(transition); |
47 item->SetTimestamp(base::Time::Now()); | 41 item->SetTimestamp(base::Time::Now()); |
48 item->SetPostData([@"Test data" dataUsingEncoding:NSUTF8StringEncoding]); | 42 item->SetPostData([@"Test data" dataUsingEncoding:NSUTF8StringEncoding]); |
49 sessionEntry_.reset( | 43 sessionEntry_.reset( |
50 [[CRWSessionEntry alloc] initWithNavigationItem:std::move(item)]); | 44 [[CRWSessionEntry alloc] initWithNavigationItem:std::move(item)]); |
51 } | 45 } |
52 void TearDown() override { sessionEntry_.reset(); } | 46 void TearDown() override { sessionEntry_.reset(); } |
53 | 47 |
54 protected: | 48 protected: |
55 base::scoped_nsobject<CRWSessionEntry> sessionEntry_; | 49 base::scoped_nsobject<CRWSessionEntry> sessionEntry_; |
56 }; | 50 }; |
57 | 51 |
58 @implementation OCMockComplexTypeHelper (CRWSessionEntryTest) | |
59 typedef void (^encodeBytes_length_forKey_block)( | |
60 const uint8_t*, NSUInteger, NSString*); | |
61 - (void)encodeBytes:(const uint8_t*)bytes | |
62 length:(NSUInteger)length | |
63 forKey:(NSString*)key { | |
64 static_cast<encodeBytes_length_forKey_block>([self blockForSelector:_cmd])( | |
65 bytes, length, key); | |
66 } | |
67 | |
68 typedef const uint8_t* (^decodeBytesForKeyBlock)(NSString*, NSUInteger*); | |
69 - (const uint8_t*)decodeBytesForKey:(NSString*)key | |
70 returnedLength:(NSUInteger*)lengthp { | |
71 return static_cast<decodeBytesForKeyBlock>([self blockForSelector:_cmd])( | |
72 key, lengthp); | |
73 } | |
74 @end | |
75 | |
76 void CRWSessionEntryTest::expectEqualSessionEntries( | 52 void CRWSessionEntryTest::expectEqualSessionEntries( |
77 CRWSessionEntry* entry1, | 53 CRWSessionEntry* entry1, |
78 CRWSessionEntry* entry2, | 54 CRWSessionEntry* entry2, |
79 ui::PageTransition transition) { | 55 ui::PageTransition transition) { |
80 web::NavigationItemImpl* navItem1 = entry1.navigationItemImpl; | 56 web::NavigationItemImpl* navItem1 = entry1.navigationItemImpl; |
81 web::NavigationItemImpl* navItem2 = entry2.navigationItemImpl; | 57 web::NavigationItemImpl* navItem2 = entry2.navigationItemImpl; |
82 // url is not compared because it could differ after copy or archive. | 58 // url is not compared because it could differ after copy or archive. |
83 EXPECT_EQ(navItem1->GetVirtualURL(), navItem2->GetVirtualURL()); | 59 EXPECT_EQ(navItem1->GetVirtualURL(), navItem2->GetVirtualURL()); |
84 EXPECT_EQ(navItem1->GetReferrer().url, navItem2->GetReferrer().url); | 60 EXPECT_EQ(navItem1->GetReferrer().url, navItem2->GetReferrer().url); |
85 EXPECT_EQ(navItem1->GetTimestamp(), navItem2->GetTimestamp()); | 61 EXPECT_EQ(navItem1->GetTimestamp(), navItem2->GetTimestamp()); |
(...skipping 12 matching lines...) Expand all Loading... |
98 } | 74 } |
99 | 75 |
100 TEST_F(CRWSessionEntryTest, Description) { | 76 TEST_F(CRWSessionEntryTest, Description) { |
101 [sessionEntry_ navigationItem]->SetTitle(base::SysNSStringToUTF16(@"Title")); | 77 [sessionEntry_ navigationItem]->SetTitle(base::SysNSStringToUTF16(@"Title")); |
102 EXPECT_NSEQ([sessionEntry_ description], | 78 EXPECT_NSEQ([sessionEntry_ description], |
103 @"url:http://init.test/ originalurl:http://init.test/ " | 79 @"url:http://init.test/ originalurl:http://init.test/ " |
104 @"title:Title transition:2 displayState:{ scrollOffset:(nan, " | 80 @"title:Title transition:2 displayState:{ scrollOffset:(nan, " |
105 @"nan), zoomScaleRange:(nan, nan), zoomScale:nan } desktopUA:0"); | 81 @"nan), zoomScaleRange:(nan, nan), zoomScale:nan } desktopUA:0"); |
106 } | 82 } |
107 | 83 |
108 TEST_F(CRWSessionEntryTest, InitWithCoder) { | |
109 web::NavigationItem* item = [sessionEntry_ navigationItem]; | |
110 item->SetVirtualURL(GURL("http://user.friendly")); | |
111 item->SetTitle(base::SysNSStringToUTF16(@"Title")); | |
112 // Old serialized entries have no timestamp. | |
113 item->SetTimestamp(base::Time::FromInternalValue(0)); | |
114 | |
115 NSURL* virtualUrl = net::NSURLWithGURL(item->GetVirtualURL()); | |
116 NSURL* referrer = net::NSURLWithGURL(item->GetReferrer().url); | |
117 NSString* title = base::SysUTF16ToNSString(item->GetTitle()); | |
118 base::scoped_nsobject<id> decoder([[OCMockComplexTypeHelper alloc] | |
119 initWithRepresentedObject:[OCMockObject mockForClass:[NSCoder class]]]); | |
120 | |
121 decodeBytesForKeyBlock block = ^ const uint8_t* (NSString* key, | |
122 NSUInteger* length) { | |
123 *length = 0; | |
124 return NULL; | |
125 }; | |
126 | |
127 [[[decoder stub] andReturnValue:[NSNumber numberWithBool:NO]] | |
128 containsValueForKey:[OCMArg any]]; | |
129 | |
130 [decoder onSelector:@selector(decodeBytesForKey:returnedLength:) | |
131 callBlockExpectation:block]; | |
132 [[[decoder expect] andReturn:virtualUrl] | |
133 decodeObjectForKey:web::kSessionEntryURLDeperecatedKey]; | |
134 [[[decoder expect] andReturn:referrer] | |
135 decodeObjectForKey:web::kSessionEntryReferrerURLDeprecatedKey]; | |
136 [[[decoder expect] andReturn:title] | |
137 decodeObjectForKey:web::kSessionEntryTitleKey]; | |
138 const web::PageDisplayState& pageState = | |
139 [sessionEntry_ navigationItem]->GetPageDisplayState(); | |
140 NSDictionary* serializedPageDisplayState = | |
141 [CRWSessionEntry dictionaryFromPageDisplayState:pageState]; | |
142 [[[decoder expect] andReturn:serializedPageDisplayState] | |
143 decodeObjectForKey:web::kSessionEntryPageScrollStateKey]; | |
144 BOOL useDesktopUserAgent = | |
145 [sessionEntry_ navigationItem]->IsOverridingUserAgent(); | |
146 [[[decoder expect] andReturnValue:OCMOCK_VALUE(useDesktopUserAgent)] | |
147 decodeBoolForKey:web::kSessionEntryUseDesktopUserAgentKey]; | |
148 NSDictionary* requestHeaders = | |
149 [sessionEntry_ navigationItem]->GetHttpRequestHeaders(); | |
150 [[[decoder expect] andReturn:requestHeaders] | |
151 decodeObjectForKey:web::kSessionEntryHTTPRequestHeadersKey]; | |
152 [[[decoder expect] | |
153 andReturn:[sessionEntry_ navigationItemImpl]->GetPostData()] | |
154 decodeObjectForKey:web::kSessionEntryPOSTDataKey]; | |
155 BOOL skipRepostFormConfirmation = | |
156 [sessionEntry_ navigationItemImpl]->ShouldSkipRepostFormConfirmation(); | |
157 [[[decoder expect] andReturnValue:OCMOCK_VALUE(skipRepostFormConfirmation)] | |
158 decodeBoolForKey:web::kSessionEntrySkipRepostFormConfirmationKey]; | |
159 | |
160 base::scoped_nsobject<CRWSessionEntry> newSessionEntry( | |
161 [[CRWSessionEntry alloc] initWithCoder:decoder]); | |
162 web::NavigationItem* newItem = [newSessionEntry navigationItem]; | |
163 | |
164 EXPECT_OCMOCK_VERIFY(decoder); | |
165 expectEqualSessionEntries(sessionEntry_, newSessionEntry, | |
166 ui::PAGE_TRANSITION_RELOAD); | |
167 EXPECT_NE(item->GetURL(), newItem->GetURL()); | |
168 EXPECT_EQ(item->GetVirtualURL(), newItem->GetURL()); | |
169 } | |
170 | |
171 TEST_F(CRWSessionEntryTest, InitWithCoderNewStyle) { | |
172 web::NavigationItem* item = [sessionEntry_ navigationItem]; | |
173 item->SetVirtualURL(GURL("http://user.friendly")); | |
174 item->SetTitle(base::SysNSStringToUTF16(@"Title")); | |
175 int64_t timestamp = item->GetTimestamp().ToInternalValue(); | |
176 | |
177 std::string virtualUrl = item->GetVirtualURL().spec(); | |
178 std::string referrerUrl = item->GetReferrer().url.spec(); | |
179 NSString* title = base::SysUTF16ToNSString(item->GetTitle()); | |
180 base::scoped_nsobject<id> decoder([[OCMockComplexTypeHelper alloc] | |
181 initWithRepresentedObject:[OCMockObject mockForClass:[NSCoder class]]]); | |
182 | |
183 const std::string emptyString; | |
184 decodeBytesForKeyBlock block = ^ const uint8_t* (NSString* key, | |
185 NSUInteger* length) { | |
186 const std::string *value = &emptyString; | |
187 if ([key isEqualToString:web::kSessionEntryURLKey]) | |
188 value = &virtualUrl; | |
189 else if ([key isEqualToString:web::kSessionEntryReferrerURLKey]) | |
190 value = &referrerUrl; | |
191 else | |
192 EXPECT_TRUE(false); | |
193 | |
194 *length = value->size(); | |
195 return reinterpret_cast<const uint8_t*>(value->data()); | |
196 }; | |
197 | |
198 [decoder onSelector:@selector(decodeBytesForKey:returnedLength:) | |
199 callBlockExpectation:block]; | |
200 [[[decoder stub] andReturnValue:[NSNumber numberWithBool:YES]] | |
201 containsValueForKey:[OCMArg any]]; | |
202 web::ReferrerPolicy expectedPolicy = item->GetReferrer().policy; | |
203 [[[decoder expect] andReturnValue:OCMOCK_VALUE(expectedPolicy)] | |
204 decodeIntForKey:web::kSessionEntryReferrerPolicyKey]; | |
205 [[[decoder expect] andReturnValue:OCMOCK_VALUE(timestamp)] | |
206 decodeInt64ForKey:web::kSessionEntryTimestampKey]; | |
207 [[[decoder expect] andReturn:title] | |
208 decodeObjectForKey:web::kSessionEntryTitleKey]; | |
209 const web::PageDisplayState& pageState = | |
210 [sessionEntry_ navigationItem]->GetPageDisplayState(); | |
211 NSDictionary* serializedPageDisplayState = | |
212 [CRWSessionEntry dictionaryFromPageDisplayState:pageState]; | |
213 [[[decoder expect] andReturn:serializedPageDisplayState] | |
214 decodeObjectForKey:web::kSessionEntryPageScrollStateKey]; | |
215 BOOL useDesktopUserAgent = | |
216 [sessionEntry_ navigationItem]->IsOverridingUserAgent(); | |
217 [[[decoder expect] andReturnValue:OCMOCK_VALUE(useDesktopUserAgent)] | |
218 decodeBoolForKey:web::kSessionEntryUseDesktopUserAgentKey]; | |
219 NSDictionary* requestHeaders = | |
220 [sessionEntry_ navigationItem]->GetHttpRequestHeaders(); | |
221 [[[decoder expect] andReturn:requestHeaders] | |
222 decodeObjectForKey:web::kSessionEntryHTTPRequestHeadersKey]; | |
223 NSData* POSTData = [sessionEntry_ navigationItemImpl]->GetPostData(); | |
224 [[[decoder expect] andReturn:POSTData] | |
225 decodeObjectForKey:web::kSessionEntryPOSTDataKey]; | |
226 BOOL skipRepostFormConfirmation = | |
227 [sessionEntry_ navigationItemImpl]->ShouldSkipRepostFormConfirmation(); | |
228 [[[decoder expect] andReturnValue:OCMOCK_VALUE(skipRepostFormConfirmation)] | |
229 decodeBoolForKey:web::kSessionEntrySkipRepostFormConfirmationKey]; | |
230 | |
231 base::scoped_nsobject<CRWSessionEntry> newSessionEntry( | |
232 [[CRWSessionEntry alloc] initWithCoder:decoder]); | |
233 web::NavigationItem* newItem = [newSessionEntry navigationItem]; | |
234 | |
235 EXPECT_OCMOCK_VERIFY(decoder); | |
236 expectEqualSessionEntries(sessionEntry_, newSessionEntry, | |
237 ui::PAGE_TRANSITION_RELOAD); | |
238 EXPECT_NE(item->GetURL(), newItem->GetURL()); | |
239 EXPECT_EQ(item->GetVirtualURL(), newItem->GetVirtualURL()); | |
240 } | |
241 | |
242 TEST_F(CRWSessionEntryTest, EncodeDecode) { | |
243 NSData *data = | |
244 [NSKeyedArchiver archivedDataWithRootObject:sessionEntry_]; | |
245 id decoded = [NSKeyedUnarchiver unarchiveObjectWithData:data]; | |
246 | |
247 expectEqualSessionEntries(sessionEntry_, decoded, | |
248 ui::PAGE_TRANSITION_RELOAD); | |
249 } | |
250 | |
251 TEST_F(CRWSessionEntryTest, EncodeWithCoder) { | |
252 web::NavigationItem* item = [sessionEntry_ navigationItem]; | |
253 NSString* title = base::SysUTF16ToNSString(item->GetTitle()); | |
254 | |
255 base::scoped_nsobject<id> coder([[OCMockComplexTypeHelper alloc] | |
256 initWithRepresentedObject:[OCMockObject mockForClass:[NSCoder class]]]); | |
257 | |
258 encodeBytes_length_forKey_block block = | |
259 ^(const uint8_t* bytes, NSUInteger length, NSString* key) { | |
260 if ([key isEqualToString:web::kSessionEntryURLKey]) { | |
261 ASSERT_EQ(item->GetVirtualURL().spec(), | |
262 std::string(reinterpret_cast<const char*>(bytes), length)); | |
263 return; | |
264 } else if ([key isEqualToString:web::kSessionEntryReferrerURLKey]) { | |
265 ASSERT_EQ(item->GetReferrer().url.spec(), | |
266 std::string(reinterpret_cast<const char*>(bytes), length)); | |
267 return; | |
268 } | |
269 FAIL(); | |
270 }; | |
271 [coder onSelector:@selector(encodeBytes:length:forKey:) | |
272 callBlockExpectation:block]; | |
273 [[coder expect] encodeInt:item->GetReferrer().policy | |
274 forKey:web::kSessionEntryReferrerPolicyKey]; | |
275 [[coder expect] encodeInt64:item->GetTimestamp().ToInternalValue() | |
276 forKey:web::kSessionEntryTimestampKey]; | |
277 [[coder expect] encodeObject:title forKey:web::kSessionEntryTitleKey]; | |
278 const web::PageDisplayState& pageState = | |
279 [sessionEntry_ navigationItem]->GetPageDisplayState(); | |
280 NSDictionary* serializedPageDisplayState = | |
281 [CRWSessionEntry dictionaryFromPageDisplayState:pageState]; | |
282 [[coder expect] encodeObject:serializedPageDisplayState | |
283 forKey:web::kSessionEntryPageScrollStateKey]; | |
284 BOOL useDesktopUserAgent = | |
285 [sessionEntry_ navigationItem]->IsOverridingUserAgent(); | |
286 [[coder expect] encodeBool:useDesktopUserAgent | |
287 forKey:web::kSessionEntryUseDesktopUserAgentKey]; | |
288 NSDictionary* requestHeaders = | |
289 [sessionEntry_ navigationItem]->GetHttpRequestHeaders(); | |
290 [[coder expect] encodeObject:requestHeaders | |
291 forKey:web::kSessionEntryHTTPRequestHeadersKey]; | |
292 [[coder expect] encodeObject:[sessionEntry_ navigationItemImpl]->GetPostData() | |
293 forKey:web::kSessionEntryPOSTDataKey]; | |
294 BOOL skipRepostFormConfirmation = | |
295 [sessionEntry_ navigationItemImpl]->ShouldSkipRepostFormConfirmation(); | |
296 [[coder expect] encodeBool:skipRepostFormConfirmation | |
297 forKey:web::kSessionEntrySkipRepostFormConfirmationKey]; | |
298 [sessionEntry_ encodeWithCoder:coder]; | |
299 EXPECT_OCMOCK_VERIFY(coder); | |
300 } | |
301 | |
302 TEST_F(CRWSessionEntryTest, CodingEncoding) { | |
303 web::NavigationItem* item = [sessionEntry_ navigationItem]; | |
304 item->SetVirtualURL(GURL("http://user.friendly")); | |
305 NSData* data = [NSKeyedArchiver archivedDataWithRootObject:sessionEntry_]; | |
306 EXPECT_TRUE(data != nil); | |
307 CRWSessionEntry* unarchivedSessionEntry = | |
308 [NSKeyedUnarchiver unarchiveObjectWithData:data]; | |
309 ASSERT_TRUE(unarchivedSessionEntry != nil); | |
310 web::NavigationItem* unarchivedItem = [unarchivedSessionEntry navigationItem]; | |
311 expectEqualSessionEntries(sessionEntry_, unarchivedSessionEntry, | |
312 ui::PAGE_TRANSITION_RELOAD); | |
313 EXPECT_EQ(unarchivedItem->GetURL(), item->GetVirtualURL()); | |
314 EXPECT_NE(unarchivedItem->GetURL(), item->GetURL()); | |
315 } | |
316 | |
317 TEST_F(CRWSessionEntryTest, CopyWithZone) { | 84 TEST_F(CRWSessionEntryTest, CopyWithZone) { |
318 CRWSessionEntry* sessionEntry2 = [sessionEntry_ copy]; | 85 CRWSessionEntry* sessionEntry2 = [sessionEntry_ copy]; |
319 EXPECT_NE(sessionEntry_, sessionEntry2); | 86 EXPECT_NE(sessionEntry_, sessionEntry2); |
320 expectEqualSessionEntries( | 87 expectEqualSessionEntries( |
321 sessionEntry_, sessionEntry2, | 88 sessionEntry_, sessionEntry2, |
322 [sessionEntry_ navigationItem]->GetTransitionType()); | 89 [sessionEntry_ navigationItem]->GetTransitionType()); |
323 } | 90 } |
324 | 91 |
325 TEST_F(CRWSessionEntryTest, EmptyVirtualUrl) { | 92 TEST_F(CRWSessionEntryTest, EmptyVirtualUrl) { |
326 EXPECT_EQ(GURL("http://init.test/"), | 93 EXPECT_EQ(GURL("http://init.test/"), |
327 [sessionEntry_ navigationItem]->GetURL()); | 94 [sessionEntry_ navigationItem]->GetURL()); |
328 } | 95 } |
329 | 96 |
330 TEST_F(CRWSessionEntryTest, NonEmptyVirtualUrl) { | 97 TEST_F(CRWSessionEntryTest, NonEmptyVirtualUrl) { |
331 web::NavigationItem* item = [sessionEntry_ navigationItem]; | 98 web::NavigationItem* item = [sessionEntry_ navigationItem]; |
332 item->SetVirtualURL(GURL("http://user.friendly")); | 99 item->SetVirtualURL(GURL("http://user.friendly")); |
333 EXPECT_EQ(GURL("http://user.friendly/"), item->GetVirtualURL()); | 100 EXPECT_EQ(GURL("http://user.friendly/"), item->GetVirtualURL()); |
334 EXPECT_EQ(GURL("http://init.test/"), item->GetURL()); | 101 EXPECT_EQ(GURL("http://init.test/"), item->GetURL()); |
335 } | 102 } |
336 | 103 |
337 TEST_F(CRWSessionEntryTest, EmptyDescription) { | 104 TEST_F(CRWSessionEntryTest, EmptyDescription) { |
338 EXPECT_GT([[sessionEntry_ description] length], 0U); | 105 EXPECT_GT([[sessionEntry_ description] length], 0U); |
339 } | 106 } |
OLD | NEW |