Home | History | Annotate | Download | only in wml
      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
    230