a5d45a9a80ee8582ab5d3ff9a78268dfcbdb9205
[WebKit-https.git] / Source / WebKit / WebProcess / WebCoreSupport / SessionStateConversion.cpp
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "SessionStateConversion.h"
28
29 #include "SessionState.h"
30 #include <WebCore/BlobData.h>
31 #include <WebCore/FileSystem.h>
32 #include <WebCore/FormData.h>
33 #include <WebCore/HistoryItem.h>
34
35 using namespace WebCore;
36
37 namespace WebKit {
38
39 static HTTPBody toHTTPBody(const FormData& formData)
40 {
41     HTTPBody httpBody;
42
43     for (const auto& formDataElement : formData.elements()) {
44         HTTPBody::Element element;
45
46         switch (formDataElement.m_type) {
47         case FormDataElement::Type::Data:
48             element.type = HTTPBody::Element::Type::Data;
49             element.data = formDataElement.m_data;
50             break;
51
52         case FormDataElement::Type::EncodedFile:
53             element.filePath = formDataElement.m_filename;
54             element.fileStart = formDataElement.m_fileStart;
55             if (formDataElement.m_fileLength != BlobDataItem::toEndOfFile)
56                 element.fileLength = formDataElement.m_fileLength;
57             if (formDataElement.m_expectedFileModificationTime != FileSystem::invalidFileTime())
58                 element.expectedFileModificationTime = formDataElement.m_expectedFileModificationTime;
59             break;
60
61         case FormDataElement::Type::EncodedBlob:
62             element.blobURLString = formDataElement.m_url.string();
63             break;
64         }
65
66         httpBody.elements.append(WTFMove(element));
67     }
68
69     return httpBody;
70 }
71
72 static FrameState toFrameState(const HistoryItem& historyItem)
73 {
74     FrameState frameState;
75
76     frameState.urlString = historyItem.urlString();
77     frameState.originalURLString = historyItem.originalURLString();
78     frameState.referrer = historyItem.referrer();
79     frameState.target = historyItem.target();
80
81     frameState.documentState = historyItem.documentState();
82     if (RefPtr<SerializedScriptValue> stateObject = historyItem.stateObject())
83         frameState.stateObjectData = stateObject->data();
84
85     frameState.documentSequenceNumber = historyItem.documentSequenceNumber();
86     frameState.itemSequenceNumber = historyItem.itemSequenceNumber();
87
88     frameState.scrollPosition = historyItem.scrollPosition();
89     frameState.shouldRestoreScrollPosition = historyItem.shouldRestoreScrollPosition();
90     frameState.pageScaleFactor = historyItem.pageScaleFactor();
91
92     if (FormData* formData = const_cast<HistoryItem&>(historyItem).formData()) {
93         HTTPBody httpBody = toHTTPBody(*formData);
94         httpBody.contentType = historyItem.formContentType();
95
96         frameState.httpBody = WTFMove(httpBody);
97     }
98
99 #if PLATFORM(IOS)
100     frameState.exposedContentRect = historyItem.exposedContentRect();
101     frameState.unobscuredContentRect = historyItem.unobscuredContentRect();
102     frameState.minimumLayoutSizeInScrollViewCoordinates = historyItem.minimumLayoutSizeInScrollViewCoordinates();
103     frameState.contentSize = historyItem.contentSize();
104     frameState.scaleIsInitial = historyItem.scaleIsInitial();
105 #endif
106
107     for (auto& childHistoryItem : historyItem.children()) {
108         FrameState childFrameState = toFrameState(childHistoryItem);
109         frameState.children.append(WTFMove(childFrameState));
110     }
111
112     return frameState;
113 }
114
115 PageState toPageState(const WebCore::HistoryItem& historyItem)
116 {
117     PageState pageState;
118
119     pageState.title = historyItem.title();
120     pageState.mainFrameState = toFrameState(historyItem);
121     pageState.shouldOpenExternalURLsPolicy = historyItem.shouldOpenExternalURLsPolicy();
122     pageState.sessionStateObject = historyItem.stateObject();
123     return pageState;
124 }
125
126 static Ref<FormData> toFormData(const HTTPBody& httpBody)
127 {
128     auto formData = FormData::create();
129
130     for (const auto& element : httpBody.elements) {
131         switch (element.type) {
132         case HTTPBody::Element::Type::Data:
133             formData->appendData(element.data.data(), element.data.size());
134             break;
135
136         case HTTPBody::Element::Type::File:
137             formData->appendFileRange(element.filePath, element.fileStart, element.fileLength.value_or(BlobDataItem::toEndOfFile), element.expectedFileModificationTime.value_or(FileSystem::invalidFileTime()));
138             break;
139
140         case HTTPBody::Element::Type::Blob:
141             formData->appendBlob(URL(URL(), element.blobURLString));
142             break;
143         }
144     }
145
146     return formData;
147 }
148
149 static void applyFrameState(HistoryItem& historyItem, const FrameState& frameState)
150 {
151     historyItem.setOriginalURLString(frameState.originalURLString);
152     historyItem.setReferrer(frameState.referrer);
153     historyItem.setTarget(frameState.target);
154
155     historyItem.setDocumentState(frameState.documentState);
156
157     if (frameState.stateObjectData) {
158         Vector<uint8_t> stateObjectData = frameState.stateObjectData.value();
159         historyItem.setStateObject(SerializedScriptValue::adopt(WTFMove(stateObjectData)));
160     }
161
162     historyItem.setDocumentSequenceNumber(frameState.documentSequenceNumber);
163     historyItem.setItemSequenceNumber(frameState.itemSequenceNumber);
164
165     historyItem.setScrollPosition(frameState.scrollPosition);
166     historyItem.setShouldRestoreScrollPosition(frameState.shouldRestoreScrollPosition);
167     historyItem.setPageScaleFactor(frameState.pageScaleFactor);
168
169     if (frameState.httpBody) {
170         const auto& httpBody = frameState.httpBody.value();
171         historyItem.setFormContentType(httpBody.contentType);
172
173         historyItem.setFormData(toFormData(httpBody));
174     }
175
176 #if PLATFORM(IOS)
177     historyItem.setExposedContentRect(frameState.exposedContentRect);
178     historyItem.setUnobscuredContentRect(frameState.unobscuredContentRect);
179     historyItem.setMinimumLayoutSizeInScrollViewCoordinates(frameState.minimumLayoutSizeInScrollViewCoordinates);
180     historyItem.setContentSize(frameState.contentSize);
181     historyItem.setScaleIsInitial(frameState.scaleIsInitial);
182 #endif
183
184     for (const auto& childFrameState : frameState.children) {
185         Ref<HistoryItem> childHistoryItem = HistoryItem::create(childFrameState.urlString, String());
186         applyFrameState(childHistoryItem, childFrameState);
187
188         historyItem.addChildItem(WTFMove(childHistoryItem));
189     }
190 }
191
192 Ref<HistoryItem> toHistoryItem(const PageState& pageState)
193 {
194     Ref<HistoryItem> historyItem = HistoryItem::create(pageState.mainFrameState.urlString, pageState.title);
195     historyItem->setShouldOpenExternalURLsPolicy(pageState.shouldOpenExternalURLsPolicy);
196     historyItem->setStateObject(pageState.sessionStateObject.get());
197     applyFrameState(historyItem, pageState.mainFrameState);
198
199     return historyItem;
200 }
201
202 } // namespace WebKit