f283c728630ed4e424d6d0bdd4e2806e28234802
[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 namespace WebKit {
36 using namespace WebCore;
37
38 static HTTPBody toHTTPBody(const FormData& formData)
39 {
40     HTTPBody httpBody;
41
42     for (const auto& formDataElement : formData.elements()) {
43         HTTPBody::Element element;
44
45         switchOn(formDataElement.data,
46             [&] (const Vector<char>& bytes) {
47                 element.type = HTTPBody::Element::Type::Data;
48                 element.data = bytes;
49             }, [&] (const FormDataElement::EncodedFileData& fileData) {
50                 element.filePath = fileData.filename;
51                 element.fileStart = fileData.fileStart;
52                 if (fileData.fileLength != BlobDataItem::toEndOfFile)
53                     element.fileLength = fileData.fileLength;
54                 element.expectedFileModificationTime = fileData.expectedFileModificationTime;
55             }, [&] (const FormDataElement::EncodedBlobData& blobData) {
56                 element.blobURLString = blobData.url.string();
57             }
58         );
59
60         httpBody.elements.append(WTFMove(element));
61     }
62
63     return httpBody;
64 }
65
66 static FrameState toFrameState(const HistoryItem& historyItem)
67 {
68     FrameState frameState;
69
70     frameState.urlString = historyItem.urlString();
71     frameState.originalURLString = historyItem.originalURLString();
72     frameState.referrer = historyItem.referrer();
73     frameState.target = historyItem.target();
74
75     frameState.documentState = historyItem.documentState();
76     if (RefPtr<SerializedScriptValue> stateObject = historyItem.stateObject())
77         frameState.stateObjectData = stateObject->data();
78
79     frameState.documentSequenceNumber = historyItem.documentSequenceNumber();
80     frameState.itemSequenceNumber = historyItem.itemSequenceNumber();
81
82     frameState.scrollPosition = historyItem.scrollPosition();
83     frameState.shouldRestoreScrollPosition = historyItem.shouldRestoreScrollPosition();
84     frameState.pageScaleFactor = historyItem.pageScaleFactor();
85
86     if (FormData* formData = const_cast<HistoryItem&>(historyItem).formData()) {
87         HTTPBody httpBody = toHTTPBody(*formData);
88         httpBody.contentType = historyItem.formContentType();
89
90         frameState.httpBody = WTFMove(httpBody);
91     }
92
93 #if PLATFORM(IOS_FAMILY)
94     frameState.exposedContentRect = historyItem.exposedContentRect();
95     frameState.unobscuredContentRect = historyItem.unobscuredContentRect();
96     frameState.minimumLayoutSizeInScrollViewCoordinates = historyItem.minimumLayoutSizeInScrollViewCoordinates();
97     frameState.contentSize = historyItem.contentSize();
98     frameState.scaleIsInitial = historyItem.scaleIsInitial();
99 #endif
100
101     for (auto& childHistoryItem : historyItem.children()) {
102         FrameState childFrameState = toFrameState(childHistoryItem);
103         frameState.children.append(WTFMove(childFrameState));
104     }
105
106     return frameState;
107 }
108
109 BackForwardListItemState toBackForwardListItemState(const WebCore::HistoryItem& historyItem)
110 {
111     BackForwardListItemState state;
112     state.identifier = historyItem.identifier();
113     state.pageState.title = historyItem.title();
114     state.pageState.mainFrameState = toFrameState(historyItem);
115     state.pageState.shouldOpenExternalURLsPolicy = historyItem.shouldOpenExternalURLsPolicy();
116     state.pageState.sessionStateObject = historyItem.stateObject();
117     return state;
118 }
119
120 static Ref<FormData> toFormData(const HTTPBody& httpBody)
121 {
122     auto formData = FormData::create();
123
124     for (const auto& element : httpBody.elements) {
125         switch (element.type) {
126         case HTTPBody::Element::Type::Data:
127             formData->appendData(element.data.data(), element.data.size());
128             break;
129
130         case HTTPBody::Element::Type::File:
131             formData->appendFileRange(element.filePath, element.fileStart, element.fileLength.value_or(BlobDataItem::toEndOfFile), element.expectedFileModificationTime);
132             break;
133
134         case HTTPBody::Element::Type::Blob:
135             formData->appendBlob(URL(URL(), element.blobURLString));
136             break;
137         }
138     }
139
140     return formData;
141 }
142
143 static void applyFrameState(HistoryItem& historyItem, const FrameState& frameState)
144 {
145     historyItem.setOriginalURLString(frameState.originalURLString);
146     historyItem.setReferrer(frameState.referrer);
147     historyItem.setTarget(frameState.target);
148
149     historyItem.setDocumentState(frameState.documentState);
150
151     if (frameState.stateObjectData) {
152         Vector<uint8_t> stateObjectData = frameState.stateObjectData.value();
153         historyItem.setStateObject(SerializedScriptValue::adopt(WTFMove(stateObjectData)));
154     }
155
156     historyItem.setDocumentSequenceNumber(frameState.documentSequenceNumber);
157     historyItem.setItemSequenceNumber(frameState.itemSequenceNumber);
158
159     historyItem.setScrollPosition(frameState.scrollPosition);
160     historyItem.setShouldRestoreScrollPosition(frameState.shouldRestoreScrollPosition);
161     historyItem.setPageScaleFactor(frameState.pageScaleFactor);
162
163     if (frameState.httpBody) {
164         const auto& httpBody = frameState.httpBody.value();
165         historyItem.setFormContentType(httpBody.contentType);
166
167         historyItem.setFormData(toFormData(httpBody));
168     }
169
170 #if PLATFORM(IOS_FAMILY)
171     historyItem.setExposedContentRect(frameState.exposedContentRect);
172     historyItem.setUnobscuredContentRect(frameState.unobscuredContentRect);
173     historyItem.setMinimumLayoutSizeInScrollViewCoordinates(frameState.minimumLayoutSizeInScrollViewCoordinates);
174     historyItem.setContentSize(frameState.contentSize);
175     historyItem.setScaleIsInitial(frameState.scaleIsInitial);
176 #endif
177
178     for (const auto& childFrameState : frameState.children) {
179         Ref<HistoryItem> childHistoryItem = HistoryItem::create(childFrameState.urlString, { }, { }, { Process::identifier(), generateObjectIdentifier<BackForwardItemIdentifier::ItemIdentifierType>() });
180         applyFrameState(childHistoryItem, childFrameState);
181
182         historyItem.addChildItem(WTFMove(childHistoryItem));
183     }
184 }
185
186 Ref<HistoryItem> toHistoryItem(const BackForwardListItemState& itemState)
187 {
188     Ref<HistoryItem> historyItem = HistoryItem::create(itemState.pageState.mainFrameState.urlString, itemState.pageState.title, { }, itemState.identifier);
189     historyItem->setShouldOpenExternalURLsPolicy(itemState.pageState.shouldOpenExternalURLsPolicy);
190     historyItem->setStateObject(itemState.pageState.sessionStateObject.get());
191     applyFrameState(historyItem, itemState.pageState.mainFrameState);
192
193     return historyItem;
194 }
195
196 } // namespace WebKit