WebCore/wml/WMLGoElement.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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 "Frame.h"
       
    29 #include "FrameLoader.h"
       
    30 #include "HTMLNames.h"
       
    31 #include "ResourceRequest.h"
       
    32 #include "TextEncoding.h"
       
    33 #include "WMLCardElement.h"
       
    34 #include "WMLDocument.h"
       
    35 #include "WMLNames.h"
       
    36 #include "WMLPageState.h"
       
    37 #include "WMLPostfieldElement.h"
       
    38 #include "WMLTimerElement.h"
       
    39 #include "WMLVariables.h"
       
    40 #include <wtf/text/CString.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(Attribute* 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