OSDN Git Service

am 741c2272: (-s ours) am d3bed0e7: Cherry-pick WebKit security fix (webkit.org r6809...
[android-x86/external-webkit.git] / WebCore / wml / WMLGoElement.cpp
1 /**
2  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #include "config.h"
22
23 #if ENABLE(WML)
24 #include "WMLGoElement.h"
25
26 #include "Attribute.h"
27 #include "FormData.h"
28 #include "FormDataBuilder.h"
29 #include "FormSubmission.h"
30 #include "Frame.h"
31 #include "FrameLoader.h"
32 #include "HTMLNames.h"
33 #include "ResourceRequest.h"
34 #include "TextEncoding.h"
35 #include "WMLCardElement.h"
36 #include "WMLDocument.h"
37 #include "WMLNames.h"
38 #include "WMLPageState.h"
39 #include "WMLPostfieldElement.h"
40 #include "WMLTimerElement.h"
41 #include "WMLVariables.h"
42 #include <wtf/text/CString.h>
43
44 namespace WebCore {
45
46 using namespace WMLNames;
47
48 WMLGoElement::WMLGoElement(const QualifiedName& tagName, Document* doc)
49     : WMLTaskElement(tagName, doc)
50 {
51 }
52  
53 PassRefPtr<WMLGoElement> WMLGoElement::create(const QualifiedName& tagName, Document* document)
54 {
55     return adoptRef(new WMLGoElement(tagName, document));
56 }
57
58 void WMLGoElement::registerPostfieldElement(WMLPostfieldElement* postfield)
59 {
60     ASSERT(m_postfieldElements.find(postfield) == WTF::notFound);
61     m_postfieldElements.append(postfield);
62 }
63  
64 void WMLGoElement::deregisterPostfieldElement(WMLPostfieldElement* postfield)
65 {
66     size_t position = m_postfieldElements.find(postfield);
67     ASSERT(position != WTF::notFound);
68     m_postfieldElements.remove(position);
69 }
70
71 void WMLGoElement::parseMappedAttribute(Attribute* attr)
72 {
73     if (attr->name() == HTMLNames::methodAttr)
74         m_formAttributes.parseMethodType(attr->value());
75     else if (attr->name() == HTMLNames::enctypeAttr)
76         m_formAttributes.parseEncodingType(parseValueSubstitutingVariableReferences(attr->value()));
77     else if (attr->name() == HTMLNames::accept_charsetAttr)
78         m_formAttributes.setAcceptCharset(parseValueForbiddingVariableReferences(attr->value()));
79     else
80         WMLTaskElement::parseMappedAttribute(attr);
81 }
82
83 void WMLGoElement::executeTask()
84 {
85     ASSERT(document()->isWMLDocument());
86     WMLDocument* document = static_cast<WMLDocument*>(this->document());
87
88     WMLPageState* pageState = wmlPageStateForDocument(document);
89     if (!pageState)
90         return;
91
92     WMLCardElement* card = document->activeCard();
93     if (!card)
94         return;
95
96     Frame* frame = document->frame();
97     if (!frame)
98         return;
99
100     FrameLoader* loader = frame->loader();
101     if (!loader)
102         return;
103
104     String href = getAttribute(HTMLNames::hrefAttr);
105     if (href.isEmpty())
106         return;
107
108     // Substitute variables within target url attribute value
109     KURL url = document->completeURL(substituteVariableReferences(href, document, WMLVariableEscapingEscape));
110     if (url.isEmpty())
111         return;
112
113     storeVariableState(pageState);
114
115     // Stop the timer of the current card if it is active
116     if (WMLTimerElement* eventTimer = card->eventTimer())
117         eventTimer->stop();
118
119     // FIXME: 'newcontext' handling not implemented for external cards
120     bool inSameDeck = document->url().path() == url.path();
121     if (inSameDeck && url.hasFragmentIdentifier()) {
122         if (WMLCardElement* card = WMLCardElement::findNamedCardInDocument(document, url.fragmentIdentifier())) {
123             if (card->isNewContext())
124                 pageState->reset();
125         }
126     }
127
128     // Prepare loading the destination url
129     ResourceRequest request(url);
130
131     if (getAttribute(sendrefererAttr) == "true")
132         request.setHTTPReferrer(loader->outgoingReferrer());
133
134     String cacheControl = getAttribute(cache_controlAttr);
135
136     if (m_formAttributes.method() == FormSubmission::PostMethod)
137         preparePOSTRequest(request, inSameDeck, cacheControl);
138     else
139         prepareGETRequest(request, url);
140
141     // Set HTTP cache-control header if needed
142     if (!cacheControl.isEmpty()) {
143         request.setHTTPHeaderField("cache-control", cacheControl);
144
145         if (cacheControl == "no-cache")
146             request.setCachePolicy(ReloadIgnoringCacheData);
147     }
148
149     loader->load(request, false);
150 }
151
152 void WMLGoElement::preparePOSTRequest(ResourceRequest& request, bool inSameDeck, const String& cacheControl)
153 {
154     request.setHTTPMethod("POST");
155
156     if (inSameDeck && cacheControl != "no-cache") {
157         request.setCachePolicy(ReturnCacheDataDontLoad);
158         return;
159     }
160
161     RefPtr<FormData> data;
162
163     if (m_formAttributes.isMultiPartForm()) { // multipart/form-data
164         Vector<char> boundary = FormDataBuilder::generateUniqueBoundaryString();
165         data = createFormData(boundary.data());
166         request.setHTTPContentType(m_formAttributes.encodingType() + "; boundary=" + boundary.data());
167     } else {
168         // text/plain or application/x-www-form-urlencoded
169         data = createFormData(CString());
170         request.setHTTPContentType(m_formAttributes.encodingType());
171     }
172
173     request.setHTTPBody(data.get());
174 }
175
176 void WMLGoElement::prepareGETRequest(ResourceRequest& request, const KURL& url)
177 {
178     request.setHTTPMethod("GET");
179
180     // Eventually display error message?
181     if (m_formAttributes.isMultiPartForm())
182         return;
183
184     RefPtr<FormData> data = createFormData(CString());
185
186     KURL remoteURL(url);
187     remoteURL.setQuery(data->flattenToString());
188     request.setURL(remoteURL);
189 }
190
191 PassRefPtr<FormData> WMLGoElement::createFormData(const CString& boundary)
192 {
193     CString key;
194     CString value;
195
196     Vector<char> encodedData;
197     TextEncoding encoding = FormDataBuilder::encodingFromAcceptCharset(m_formAttributes.acceptCharset(), document()).encodingForFormSubmission();
198
199     Vector<WMLPostfieldElement*>::iterator it = m_postfieldElements.begin();
200     Vector<WMLPostfieldElement*>::iterator end = m_postfieldElements.end();
201
202     RefPtr<FormData> result = FormData::create();
203     for (; it != end; ++it) {
204         (*it)->encodeData(encoding, key, value);
205
206         if (m_formAttributes.isMultiPartForm()) {
207             Vector<char> header;
208             FormDataBuilder::beginMultiPartHeader(header, boundary, key);
209             FormDataBuilder::finishMultiPartHeader(header);
210             result->appendData(header.data(), header.size());
211
212             if (size_t dataSize = value.length())
213                 result->appendData(value.data(), dataSize);
214
215             result->appendData("\r\n", 2);
216         } else
217             FormDataBuilder::addKeyValuePairAsFormData(encodedData, key, value);
218     }
219
220     if (m_formAttributes.isMultiPartForm())
221         FormDataBuilder::addBoundaryToMultiPartHeader(encodedData, boundary, true);
222
223     result->appendData(encodedData.data(), encodedData.size());
224     return result;
225 }
226
227 }
228
229 #endif