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