• 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 "CString.h"
27 #include "FormData.h"
28 #include "Frame.h"
29 #include "FrameLoader.h"
30 #include "HTMLNames.h"
31 #include "MappedAttribute.h"
32 #include "ResourceRequest.h"
33 #include "TextEncoding.h"
34 #include "WMLCardElement.h"
35 #include "WMLDocument.h"
36 #include "WMLNames.h"
37 #include "WMLPageState.h"
38 #include "WMLPostfieldElement.h"
39 #include "WMLTimerElement.h"
40 #include "WMLVariables.h"
41 
42 namespace WebCore {
43 
44 using namespace WMLNames;
45 
WMLGoElement(const QualifiedName & tagName,Document * doc)46 WMLGoElement::WMLGoElement(const QualifiedName& tagName, Document* doc)
47     : WMLTaskElement(tagName, doc)
48 {
49 }
50 
registerPostfieldElement(WMLPostfieldElement * postfield)51 void WMLGoElement::registerPostfieldElement(WMLPostfieldElement* postfield)
52 {
53     ASSERT(m_postfieldElements.find(postfield) == WTF::notFound);
54     m_postfieldElements.append(postfield);
55 }
56 
deregisterPostfieldElement(WMLPostfieldElement * postfield)57 void WMLGoElement::deregisterPostfieldElement(WMLPostfieldElement* postfield)
58 {
59     size_t position = m_postfieldElements.find(postfield);
60     ASSERT(position != WTF::notFound);
61     m_postfieldElements.remove(position);
62 }
63 
parseMappedAttribute(MappedAttribute * attr)64 void WMLGoElement::parseMappedAttribute(MappedAttribute* attr)
65 {
66     if (attr->name() == HTMLNames::methodAttr)
67         m_formDataBuilder.parseMethodType(attr->value());
68     else if (attr->name() == HTMLNames::enctypeAttr)
69         m_formDataBuilder.parseEncodingType(parseValueSubstitutingVariableReferences(attr->value()));
70     else if (attr->name() == HTMLNames::accept_charsetAttr)
71         m_formDataBuilder.setAcceptCharset(parseValueForbiddingVariableReferences(attr->value()));
72     else
73         WMLTaskElement::parseMappedAttribute(attr);
74 }
75 
executeTask(Event *)76 void WMLGoElement::executeTask(Event*)
77 {
78     Document* doc = document();
79     WMLPageState* pageState = wmlPageStateForDocument(doc);
80     if (!pageState)
81         return;
82 
83     WMLCardElement* card = pageState->activeCard();
84     if (!card)
85         return;
86 
87     Frame* frame = doc->frame();
88     if (!frame)
89         return;
90 
91     FrameLoader* loader = frame->loader();
92     if (!loader)
93         return;
94 
95     String href = getAttribute(HTMLNames::hrefAttr);
96     if (href.isEmpty())
97         return;
98 
99     // Substitute variables within target url attribute value
100     KURL url = doc->completeURL(substituteVariableReferences(href, doc, WMLVariableEscapingEscape));
101     if (url.isEmpty())
102         return;
103 
104     storeVariableState(pageState);
105 
106     // Stop the timer of the current card if it is active
107     if (WMLTimerElement* eventTimer = card->eventTimer())
108         eventTimer->stop();
109 
110     // FIXME: 'newcontext' handling not implemented for external cards
111     bool inSameDeck = doc->url().path() == url.path();
112     if (inSameDeck && url.hasFragmentIdentifier()) {
113         if (WMLCardElement* card = WMLCardElement::findNamedCardInDocument(doc, url.fragmentIdentifier())) {
114             if (card->isNewContext())
115                 pageState->reset();
116         }
117     }
118 
119     // Prepare loading the destination url
120     ResourceRequest request(url);
121 
122     if (getAttribute(sendrefererAttr) == "true")
123         request.setHTTPReferrer(loader->outgoingReferrer());
124 
125     String cacheControl = getAttribute(cache_controlAttr);
126 
127     if (m_formDataBuilder.isPostMethod())
128         preparePOSTRequest(request, inSameDeck, cacheControl);
129     else
130         prepareGETRequest(request, url);
131 
132     // Set HTTP cache-control header if needed
133     if (!cacheControl.isEmpty()) {
134         request.setHTTPHeaderField("cache-control", cacheControl);
135 
136         if (cacheControl == "no-cache")
137             request.setCachePolicy(ReloadIgnoringCacheData);
138     }
139 
140     loader->load(request, false);
141 }
142 
preparePOSTRequest(ResourceRequest & request,bool inSameDeck,const String & cacheControl)143 void WMLGoElement::preparePOSTRequest(ResourceRequest& request, bool inSameDeck, const String& cacheControl)
144 {
145     request.setHTTPMethod("POST");
146 
147     if (inSameDeck && cacheControl != "no-cache") {
148         request.setCachePolicy(ReturnCacheDataDontLoad);
149         return;
150     }
151 
152     RefPtr<FormData> data;
153 
154     if (m_formDataBuilder.isMultiPartForm()) { // multipart/form-data
155         Vector<char> boundary = m_formDataBuilder.generateUniqueBoundaryString();
156         data = createFormData(boundary.data());
157         request.setHTTPContentType(m_formDataBuilder.encodingType() + "; boundary=" + boundary.data());
158     } else {
159         // text/plain or application/x-www-form-urlencoded
160         data = createFormData(CString());
161         request.setHTTPContentType(m_formDataBuilder.encodingType());
162     }
163 
164     request.setHTTPBody(data.get());
165 }
166 
prepareGETRequest(ResourceRequest & request,const KURL & url)167 void WMLGoElement::prepareGETRequest(ResourceRequest& request, const KURL& url)
168 {
169     request.setHTTPMethod("GET");
170 
171     // Eventually display error message?
172     if (m_formDataBuilder.isMultiPartForm())
173         return;
174 
175     RefPtr<FormData> data = createFormData(CString());
176 
177     KURL remoteURL(url);
178     remoteURL.setQuery(data->flattenToString());
179     request.setURL(remoteURL);
180 }
181 
createFormData(const CString & boundary)182 PassRefPtr<FormData> WMLGoElement::createFormData(const CString& boundary)
183 {
184     CString key;
185     CString value;
186 
187     Vector<char> encodedData;
188     TextEncoding encoding = m_formDataBuilder.dataEncoding(document()).encodingForFormSubmission();
189 
190     Vector<WMLPostfieldElement*>::iterator it = m_postfieldElements.begin();
191     Vector<WMLPostfieldElement*>::iterator end = m_postfieldElements.end();
192 
193     RefPtr<FormData> result = FormData::create();
194     for (; it != end; ++it) {
195         (*it)->encodeData(encoding, key, value);
196 
197         if (m_formDataBuilder.isMultiPartForm()) {
198             Vector<char> header;
199             m_formDataBuilder.beginMultiPartHeader(header, boundary, key);
200             m_formDataBuilder.finishMultiPartHeader(header);
201             result->appendData(header.data(), header.size());
202 
203             if (size_t dataSize = value.length())
204                 result->appendData(value.data(), dataSize);
205 
206             result->appendData("\r\n", 2);
207         } else
208             m_formDataBuilder.addKeyValuePairAsFormData(encodedData, key, value);
209     }
210 
211     if (m_formDataBuilder.isMultiPartForm())
212         m_formDataBuilder.addBoundaryToMultiPartHeader(encodedData, boundary, true);
213 
214     result->appendData(encodedData.data(), encodedData.size());
215     return result;
216 }
217 
218 }
219 
220 #endif
221