• 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