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 "content/public/common/page_state.h"
6
7#include "base/files/file_path.h"
8#include "base/strings/utf_string_conversions.h"
9#include "content/common/page_state_serialization.h"
10
11namespace content {
12namespace {
13
14base::NullableString16 ToNullableString16(const std::string& utf8) {
15  return base::NullableString16(UTF8ToUTF16(utf8), false);
16}
17
18base::FilePath ToFilePath(const base::NullableString16& s) {
19  return base::FilePath::FromUTF16Unsafe(s.string());
20}
21
22void ToFilePathVector(const std::vector<base::NullableString16>& input,
23                      std::vector<base::FilePath>* output) {
24  output->clear();
25  output->reserve(input.size());
26  for (size_t i = 0; i < input.size(); ++i)
27    output->push_back(ToFilePath(input[i]));
28}
29
30PageState ToPageState(const ExplodedPageState& state) {
31  std::string encoded_data;
32  if (!EncodePageState(state, &encoded_data))
33    return PageState();
34
35  return PageState::CreateFromEncodedData(encoded_data);
36}
37
38void RecursivelyRemovePasswordData(ExplodedFrameState* state) {
39  if (state->http_body.contains_passwords)
40    state->http_body = ExplodedHttpBody();
41}
42
43void RecursivelyRemoveScrollOffset(ExplodedFrameState* state) {
44  state->scroll_offset = gfx::Point();
45}
46
47}  // namespace
48
49// static
50PageState PageState::CreateFromEncodedData(const std::string& data) {
51  return PageState(data);
52}
53
54// static
55PageState PageState::CreateFromURL(const GURL& url) {
56  ExplodedPageState state;
57
58  state.top.url_string = state.top.original_url_string =
59      ToNullableString16(url.possibly_invalid_spec());
60
61  return ToPageState(state);
62}
63
64// static
65PageState PageState::CreateForTesting(
66    const GURL& url,
67    bool body_contains_password_data,
68    const char* optional_body_data,
69    const base::FilePath* optional_body_file_path) {
70  ExplodedPageState state;
71
72  state.top.url_string = state.top.original_url_string =
73      ToNullableString16(url.possibly_invalid_spec());
74
75  if (optional_body_data || optional_body_file_path) {
76    state.top.http_body.is_null = false;
77    if (optional_body_data) {
78      ExplodedHttpBodyElement element;
79      element.type = WebKit::WebHTTPBody::Element::TypeData;
80      element.data = optional_body_data;
81      state.top.http_body.elements.push_back(element);
82    }
83    if (optional_body_file_path) {
84      ExplodedHttpBodyElement element;
85      element.type = WebKit::WebHTTPBody::Element::TypeFile;
86      element.file_path =
87          ToNullableString16(optional_body_file_path->AsUTF8Unsafe());
88      state.top.http_body.elements.push_back(element);
89      state.referenced_files.push_back(element.file_path);
90    }
91    state.top.http_body.contains_passwords =
92        body_contains_password_data;
93  }
94
95  return ToPageState(state);
96}
97
98PageState::PageState() {
99}
100
101bool PageState::IsValid() const {
102  return !data_.empty();
103}
104
105bool PageState::Equals(const PageState& other) const {
106  return data_ == other.data_;
107}
108
109const std::string& PageState::ToEncodedData() const {
110  return data_;
111}
112
113std::vector<base::FilePath> PageState::GetReferencedFiles() const {
114  std::vector<base::FilePath> results;
115
116  ExplodedPageState state;
117  if (DecodePageState(data_, &state))
118    ToFilePathVector(state.referenced_files, &results);
119
120  return results;
121}
122
123PageState PageState::RemovePasswordData() const {
124  ExplodedPageState state;
125  if (!DecodePageState(data_, &state))
126    return PageState();  // Oops!
127
128  RecursivelyRemovePasswordData(&state.top);
129
130  return ToPageState(state);
131}
132
133PageState PageState::RemoveScrollOffset() const {
134  ExplodedPageState state;
135  if (!DecodePageState(data_, &state))
136    return PageState();  // Oops!
137
138  RecursivelyRemoveScrollOffset(&state.top);
139
140  return ToPageState(state);
141}
142
143PageState::PageState(const std::string& data)
144    : data_(data) {
145  // TODO(darin): Enable this DCHECK once tests have been fixed up to not pass
146  // bogus encoded data to CreateFromEncodedData.
147  //DCHECK(IsValid());
148}
149
150}  // namespace content
151