Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / content / common / page_state_serialization_unittest.cc
1 // Copyright 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 <math.h>
6
7 #include "base/base64.h"
8 #include "base/files/file_util.h"
9 #include "base/path_service.h"
10 #include "base/pickle.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "content/common/page_state_serialization.h"
15 #include "content/public/common/content_paths.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace content {
19 namespace {
20
21 #if defined(OS_WIN)
22 inline bool isnan(double num) { return !!_isnan(num); }
23 #endif
24
25 base::NullableString16 NS16(const char* s) {
26   return s ? base::NullableString16(base::ASCIIToUTF16(s), false) :
27              base::NullableString16();
28 }
29
30 //-----------------------------------------------------------------------------
31
32 template <typename T>
33 void ExpectEquality(const T& a, const T& b) {
34   EXPECT_EQ(a, b);
35 }
36
37 template <typename T>
38 void ExpectEquality(const std::vector<T>& a, const std::vector<T>& b) {
39   EXPECT_EQ(a.size(), b.size());
40   for (size_t i = 0; i < std::min(a.size(), b.size()); ++i)
41     ExpectEquality(a[i], b[i]);
42 }
43
44 template <>
45 void ExpectEquality(const ExplodedHttpBodyElement& a,
46                     const ExplodedHttpBodyElement& b) {
47   EXPECT_EQ(a.type, b.type);
48   EXPECT_EQ(a.data, b.data);
49   EXPECT_EQ(a.file_path, b.file_path);
50   EXPECT_EQ(a.filesystem_url, b.filesystem_url);
51   EXPECT_EQ(a.file_start, b.file_start);
52   EXPECT_EQ(a.file_length, b.file_length);
53   if (!(isnan(a.file_modification_time) && isnan(b.file_modification_time)))
54     EXPECT_DOUBLE_EQ(a.file_modification_time, b.file_modification_time);
55   EXPECT_EQ(a.blob_uuid, b.blob_uuid);
56 }
57
58 template <>
59 void ExpectEquality(const ExplodedHttpBody& a, const ExplodedHttpBody& b) {
60   EXPECT_EQ(a.http_content_type, b.http_content_type);
61   EXPECT_EQ(a.identifier, b.identifier);
62   EXPECT_EQ(a.contains_passwords, b.contains_passwords);
63   EXPECT_EQ(a.is_null, b.is_null);
64   ExpectEquality(a.elements, b.elements);
65 }
66
67 template <>
68 void ExpectEquality(const ExplodedFrameState& a, const ExplodedFrameState& b) {
69   EXPECT_EQ(a.url_string, b.url_string);
70   EXPECT_EQ(a.referrer, b.referrer);
71   EXPECT_EQ(a.referrer_policy, b.referrer_policy);
72   EXPECT_EQ(a.target, b.target);
73   EXPECT_EQ(a.state_object, b.state_object);
74   ExpectEquality(a.document_state, b.document_state);
75   EXPECT_EQ(a.pinch_viewport_scroll_offset, b.pinch_viewport_scroll_offset);
76   EXPECT_EQ(a.scroll_offset, b.scroll_offset);
77   EXPECT_EQ(a.item_sequence_number, b.item_sequence_number);
78   EXPECT_EQ(a.document_sequence_number, b.document_sequence_number);
79   EXPECT_EQ(a.page_scale_factor, b.page_scale_factor);
80   ExpectEquality(a.http_body, b.http_body);
81   ExpectEquality(a.children, b.children);
82 }
83
84 void ExpectEquality(const ExplodedPageState& a, const ExplodedPageState& b) {
85   ExpectEquality(a.referenced_files, b.referenced_files);
86   ExpectEquality(a.top, b.top);
87 }
88
89 //-----------------------------------------------------------------------------
90
91 class PageStateSerializationTest : public testing::Test {
92  public:
93   void PopulateFrameState(ExplodedFrameState* frame_state) {
94     // Invent some data for the various fields.
95     frame_state->url_string = NS16("http://dev.chromium.org/");
96     frame_state->referrer = NS16("https://www.google.com/search?q=dev.chromium.org");
97     frame_state->referrer_policy = blink::WebReferrerPolicyAlways;
98     frame_state->target = NS16("foo");
99     frame_state->state_object = NS16(NULL);
100     frame_state->document_state.push_back(NS16("1"));
101     frame_state->document_state.push_back(NS16("q"));
102     frame_state->document_state.push_back(NS16("text"));
103     frame_state->document_state.push_back(NS16("dev.chromium.org"));
104     frame_state->pinch_viewport_scroll_offset = gfx::PointF(10, 15);
105     frame_state->scroll_offset = gfx::Point(0, 100);
106     frame_state->item_sequence_number = 1;
107     frame_state->document_sequence_number = 2;
108     frame_state->frame_sequence_number = 3;
109     frame_state->page_scale_factor = 2.0;
110   }
111
112   void PopulateHttpBody(ExplodedHttpBody* http_body,
113                         std::vector<base::NullableString16>* referenced_files) {
114     http_body->is_null = false;
115     http_body->identifier = 12345;
116     http_body->contains_passwords = false;
117     http_body->http_content_type = NS16("text/foo");
118
119     ExplodedHttpBodyElement e1;
120     e1.type = blink::WebHTTPBody::Element::TypeData;
121     e1.data = "foo";
122     http_body->elements.push_back(e1);
123
124     ExplodedHttpBodyElement e2;
125     e2.type = blink::WebHTTPBody::Element::TypeFile;
126     e2.file_path = NS16("file.txt");
127     e2.file_start = 100;
128     e2.file_length = 1024;
129     e2.file_modification_time = 9999.0;
130     http_body->elements.push_back(e2);
131
132     referenced_files->push_back(e2.file_path);
133   }
134
135   void PopulateFrameStateForBackwardsCompatTest(
136       ExplodedFrameState* frame_state,
137       bool is_child) {
138     frame_state->url_string = NS16("http://chromium.org/");
139     frame_state->referrer = NS16("http://google.com/");
140     frame_state->referrer_policy = blink::WebReferrerPolicyDefault;
141     if (!is_child)
142       frame_state->target = NS16("target");
143     frame_state->pinch_viewport_scroll_offset = gfx::PointF(-1, -1);
144     frame_state->scroll_offset = gfx::Point(42, -42);
145     frame_state->item_sequence_number = 123;
146     frame_state->document_sequence_number = 456;
147     frame_state->frame_sequence_number = 789;
148     frame_state->page_scale_factor = 2.0f;
149
150     frame_state->document_state.push_back(
151         NS16("\n\r?% WebKit serialized form state version 8 \n\r=&"));
152     frame_state->document_state.push_back(NS16("form key"));
153     frame_state->document_state.push_back(NS16("1"));
154     frame_state->document_state.push_back(NS16("foo"));
155     frame_state->document_state.push_back(NS16("file"));
156     frame_state->document_state.push_back(NS16("2"));
157     frame_state->document_state.push_back(NS16("file.txt"));
158     frame_state->document_state.push_back(NS16("displayName"));
159
160     if (!is_child) {
161       frame_state->http_body.http_content_type = NS16("foo/bar");
162       frame_state->http_body.identifier = 789;
163       frame_state->http_body.is_null = false;
164
165       ExplodedHttpBodyElement e1;
166       e1.type = blink::WebHTTPBody::Element::TypeData;
167       e1.data = "first data block";
168       frame_state->http_body.elements.push_back(e1);
169
170       ExplodedHttpBodyElement e2;
171       e2.type = blink::WebHTTPBody::Element::TypeFile;
172       e2.file_path = NS16("file.txt");
173       frame_state->http_body.elements.push_back(e2);
174
175       ExplodedHttpBodyElement e3;
176       e3.type = blink::WebHTTPBody::Element::TypeData;
177       e3.data = "data the second";
178       frame_state->http_body.elements.push_back(e3);
179
180       ExplodedFrameState child_state;
181       PopulateFrameStateForBackwardsCompatTest(&child_state, true);
182       frame_state->children.push_back(child_state);
183     }
184   }
185
186   void PopulatePageStateForBackwardsCompatTest(ExplodedPageState* page_state) {
187     page_state->referenced_files.push_back(NS16("file.txt"));
188     PopulateFrameStateForBackwardsCompatTest(&page_state->top, false);
189   }
190
191   void TestBackwardsCompat(int version) {
192     const char* suffix = "";
193
194 #if defined(OS_ANDROID)
195     // Unfortunately, the format of version 11 is different on Android, so we
196     // need to use a special reference file.
197     if (version == 11)
198       suffix = "_android";
199 #endif
200
201     base::FilePath path;
202     PathService::Get(content::DIR_TEST_DATA, &path);
203     path = path.AppendASCII("page_state").AppendASCII(
204         base::StringPrintf("serialized_v%d%s.dat", version, suffix));
205
206     std::string file_contents;
207     if (!base::ReadFileToString(path, &file_contents)) {
208       ADD_FAILURE() << "File not found: " << path.value();
209       return;
210     }
211
212     std::string trimmed_contents;
213     EXPECT_TRUE(base::RemoveChars(file_contents, "\r\n", &trimmed_contents));
214
215     std::string encoded;
216     EXPECT_TRUE(base::Base64Decode(trimmed_contents, &encoded));
217
218     ExplodedPageState output;
219 #if defined(OS_ANDROID)
220     // Because version 11 of the file format unfortunately bakes in the device
221     // scale factor on Android, perform this test by assuming a preset device
222     // scale factor, ignoring the device scale factor of the current device.
223     const float kPresetDeviceScaleFactor = 2.0f;
224     EXPECT_TRUE(DecodePageStateWithDeviceScaleFactorForTesting(
225         encoded,
226         kPresetDeviceScaleFactor,
227         &output));
228 #else
229     EXPECT_TRUE(DecodePageState(encoded, &output));
230 #endif
231
232     ExplodedPageState expected;
233     PopulatePageStateForBackwardsCompatTest(&expected);
234
235     ExpectEquality(expected, output);
236   }
237 };
238
239 TEST_F(PageStateSerializationTest, BasicEmpty) {
240   ExplodedPageState input;
241
242   std::string encoded;
243   EXPECT_TRUE(EncodePageState(input, &encoded));
244
245   ExplodedPageState output;
246   EXPECT_TRUE(DecodePageState(encoded, &output));
247
248   ExpectEquality(input, output);
249 }
250
251 TEST_F(PageStateSerializationTest, BasicFrame) {
252   ExplodedPageState input;
253   PopulateFrameState(&input.top);
254
255   std::string encoded;
256   EXPECT_TRUE(EncodePageState(input, &encoded));
257
258   ExplodedPageState output;
259   EXPECT_TRUE(DecodePageState(encoded, &output));
260
261   ExpectEquality(input, output);
262 }
263
264 TEST_F(PageStateSerializationTest, BasicFramePOST) {
265   ExplodedPageState input;
266   PopulateFrameState(&input.top);
267   PopulateHttpBody(&input.top.http_body, &input.referenced_files);
268
269   std::string encoded;
270   EXPECT_TRUE(EncodePageState(input, &encoded));
271
272   ExplodedPageState output;
273   EXPECT_TRUE(DecodePageState(encoded, &output));
274
275   ExpectEquality(input, output);
276 }
277
278 TEST_F(PageStateSerializationTest, BasicFrameSet) {
279   ExplodedPageState input;
280   PopulateFrameState(&input.top);
281
282   // Add some child frames.
283   for (int i = 0; i < 4; ++i) {
284     ExplodedFrameState child_state;
285     PopulateFrameState(&child_state);
286     input.top.children.push_back(child_state);
287   }
288
289   std::string encoded;
290   EXPECT_TRUE(EncodePageState(input, &encoded));
291
292   ExplodedPageState output;
293   EXPECT_TRUE(DecodePageState(encoded, &output));
294
295   ExpectEquality(input, output);
296 }
297
298 TEST_F(PageStateSerializationTest, BasicFrameSetPOST) {
299   ExplodedPageState input;
300   PopulateFrameState(&input.top);
301
302   // Add some child frames.
303   for (int i = 0; i < 4; ++i) {
304     ExplodedFrameState child_state;
305     PopulateFrameState(&child_state);
306
307     // Simulate a form POST on a subframe.
308     if (i == 2)
309       PopulateHttpBody(&child_state.http_body, &input.referenced_files);
310
311     input.top.children.push_back(child_state);
312   }
313
314   std::string encoded;
315   EncodePageState(input, &encoded);
316
317   ExplodedPageState output;
318   DecodePageState(encoded, &output);
319
320   ExpectEquality(input, output);
321 }
322
323 TEST_F(PageStateSerializationTest, BadMessagesTest1) {
324   Pickle p;
325   // Version 14
326   p.WriteInt(14);
327   // Empty strings.
328   for (int i = 0; i < 6; ++i)
329     p.WriteInt(-1);
330   // Bad real number.
331   p.WriteInt(-1);
332
333   std::string s(static_cast<const char*>(p.data()), p.size());
334
335   ExplodedPageState output;
336   EXPECT_FALSE(DecodePageState(s, &output));
337 }
338
339 TEST_F(PageStateSerializationTest, BadMessagesTest2) {
340   double d = 0;
341   Pickle p;
342   // Version 14
343   p.WriteInt(14);
344   // Empty strings.
345   for (int i = 0; i < 6; ++i)
346     p.WriteInt(-1);
347   // More misc fields.
348   p.WriteData(reinterpret_cast<const char*>(&d), sizeof(d));
349   p.WriteInt(1);
350   p.WriteInt(1);
351   p.WriteInt(0);
352   p.WriteInt(0);
353   p.WriteInt(-1);
354   p.WriteInt(0);
355   // WebForm
356   p.WriteInt(1);
357   p.WriteInt(blink::WebHTTPBody::Element::TypeData);
358
359   std::string s(static_cast<const char*>(p.data()), p.size());
360
361   ExplodedPageState output;
362   EXPECT_FALSE(DecodePageState(s, &output));
363 }
364
365 TEST_F(PageStateSerializationTest, DumpExpectedPageStateForBackwardsCompat) {
366   // Change to #if 1 to enable this code.  Use this code to generate data, based
367   // on the current serialization format, for the BackwardsCompat_vXX tests.
368 #if 0
369   ExplodedPageState state;
370   PopulatePageStateForBackwardsCompatTest(&state);
371
372   std::string encoded;
373   EXPECT_TRUE(EncodePageState(state, &encoded));
374
375   std::string base64;
376   base::Base64Encode(encoded, &base64);
377
378   base::FilePath path;
379   PathService::Get(base::DIR_TEMP, &path);
380   path = path.AppendASCII("expected.dat");
381
382   FILE* fp = base::OpenFile(path, "wb");
383   ASSERT_TRUE(fp);
384
385   const size_t kRowSize = 76;
386   for (size_t offset = 0; offset < base64.size(); offset += kRowSize) {
387     size_t length = std::min(base64.size() - offset, kRowSize);
388     std::string segment(&base64[offset], length);
389     segment.push_back('\n');
390     ASSERT_EQ(1U, fwrite(segment.data(), segment.size(), 1, fp));
391   }
392
393   fclose(fp);
394 #endif
395 }
396
397 #if !defined(OS_ANDROID)
398 // TODO(darin): Re-enable for Android once this test accounts for systems with
399 //              a device scale factor not equal to 2.
400 TEST_F(PageStateSerializationTest, BackwardsCompat_v11) {
401   TestBackwardsCompat(11);
402 }
403 #endif
404
405 TEST_F(PageStateSerializationTest, BackwardsCompat_v12) {
406   TestBackwardsCompat(12);
407 }
408
409 TEST_F(PageStateSerializationTest, BackwardsCompat_v13) {
410   TestBackwardsCompat(13);
411 }
412
413 TEST_F(PageStateSerializationTest, BackwardsCompat_v14) {
414   TestBackwardsCompat(14);
415 }
416
417 TEST_F(PageStateSerializationTest, BackwardsCompat_v15) {
418   TestBackwardsCompat(15);
419 }
420
421 TEST_F(PageStateSerializationTest, BackwardsCompat_v16) {
422   TestBackwardsCompat(16);
423 }
424
425 TEST_F(PageStateSerializationTest, BackwardsCompat_v18) {
426   TestBackwardsCompat(18);
427 }
428
429 TEST_F(PageStateSerializationTest, BackwardsCompat_v20) {
430   TestBackwardsCompat(20);
431 }
432
433 }  // namespace
434 }  // namespace content