• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
WMLGoElement(const QualifiedName & tagName,Document * doc)48 WMLGoElement::WMLGoElement(const QualifiedName& tagName, Document* doc)
49     : WMLTaskElement(tagName, doc)
50 {
51 }
52 
create(const QualifiedName & tagName,Document * document)53 PassRefPtr<WMLGoElement> WMLGoElement::create(const QualifiedName& tagName, Document* document)
54 {
55     return adoptRef(new WMLGoElement(tagName, document));
56 }
57 
registerPostfieldElement(WMLPostfieldElement * postfield)58 void WMLGoElement::registerPostfieldElement(WMLPostfieldElement* postfield)
59 {
60     ASSERT(m_postfieldElements.find(postfield) == WTF::notFound);
61     m_postfieldElements.append(postfield);
62 }
63 
deregisterPostfieldElement(WMLPostfieldElement * postfield)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 
parseMappedAttribute(Attribute * attr)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 
executeTask()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 
preparePOSTRequest(ResourceRequest & request,bool inSameDeck,const String & cacheControl)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 
prepareGETRequest(ResourceRequest & request,const KURL & url)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 
createFormData(const CString & boundary)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
230