Home | History | Annotate | Download | only in benchmark
      1 /*
      2  * Copyright 2009, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #define LOG_TAG "webcore_test"
     27 #include "config.h"
     28 
     29 #include "Base64.h"
     30 #include "CString.h"
     31 #include "HTTPParsers.h"
     32 #include "Intercept.h"
     33 #include "ResourceHandle.h"
     34 #include "ResourceHandleClient.h"
     35 #include "ResourceRequest.h"
     36 #include "ResourceResponse.h"
     37 #include "StringHash.h"
     38 #include "TextEncoding.h"
     39 #include <utils/Log.h>
     40 #include <wtf/HashMap.h>
     41 
     42 PassRefPtr<WebCore::ResourceLoaderAndroid> MyResourceLoader::create(
     43         ResourceHandle* handle, String url)
     44 {
     45     return adoptRef<WebCore::ResourceLoaderAndroid>(
     46             new MyResourceLoader(handle, url));
     47 }
     48 
     49 void MyResourceLoader::handleRequest()
     50 {
     51     if (protocolIs(m_url, "data"))
     52         loadData(m_url.substring(5)); // 5 for data:
     53     else if (protocolIs(m_url, "file"))
     54         loadFile(m_url.substring(7)); // 7 for file://
     55 }
     56 
     57 void MyResourceLoader::loadData(const String& data)
     58 {
     59     LOGD("Loading data (%s) ...", data.latin1().data());
     60     ResourceHandleClient* client = m_handle->client();
     61     int index = data.find(',');
     62     if (index == -1) {
     63         client->cannotShowURL(m_handle);
     64         return;
     65     }
     66 
     67     String mediaType = data.substring(0, index);
     68     String base64 = data.substring(index + 1);
     69 
     70     bool decode = mediaType.endsWith(";base64", false);
     71     if (decode)
     72         mediaType = mediaType.left(mediaType.length() - 7); // 7 for base64;
     73 
     74     if (mediaType.isEmpty())
     75         mediaType = "text/plain;charset=US-ASCII";
     76 
     77     String mimeType = extractMIMETypeFromMediaType(mediaType);
     78     String charset = extractCharsetFromMediaType(mediaType);
     79 
     80     ResourceResponse response;
     81     response.setMimeType(mimeType);
     82 
     83     if (decode) {
     84         base64 = decodeURLEscapeSequences(base64);
     85         response.setTextEncodingName(charset);
     86         client->didReceiveResponse(m_handle, response);
     87 
     88         // FIXME: This is annoying. WebCore's Base64 decoder chokes on spaces.
     89         // That is correct with strict decoding but html authors (particularly
     90         // the acid3 authors) put spaces in the data which should be ignored.
     91         // Remove them here before sending to the decoder.
     92         Vector<char> in;
     93         CString str = base64.latin1();
     94         const char* chars = str.data();
     95         unsigned i = 0;
     96         while (i < str.length()) {
     97             char c = chars[i];
     98             // Don't send spaces or control characters.
     99             if (c != ' ' && c != '\n' && c != '\t' && c != '\b'
    100                     && c != '\f' && c != '\r')
    101                 in.append(chars[i]);
    102             i++;
    103         }
    104         Vector<char> out;
    105         if (base64Decode(in, out) && out.size() > 0)
    106             client->didReceiveData(m_handle, out.data(), out.size(), 0);
    107     } else {
    108         base64 = decodeURLEscapeSequences(base64, TextEncoding(charset));
    109         response.setTextEncodingName("UTF-16");
    110         client->didReceiveResponse(m_handle, response);
    111         if (base64.length() > 0)
    112             client->didReceiveData(m_handle, (const char*)base64.characters(),
    113                     base64.length() * sizeof(UChar), 0);
    114     }
    115     client->didFinishLoading(m_handle);
    116 }
    117 static String mimeTypeForExtension(const String& file)
    118 {
    119     static HashMap<String, String, CaseFoldingHash> extensionToMime;
    120     if (extensionToMime.isEmpty()) {
    121         extensionToMime.set("txt", "text/plain");
    122         extensionToMime.set("html", "text/html");
    123         extensionToMime.set("htm", "text/html");
    124         extensionToMime.set("png", "image/png");
    125         extensionToMime.set("jpeg", "image/jpeg");
    126         extensionToMime.set("jpg", "image/jpeg");
    127         extensionToMime.set("gif", "image/gif");
    128         extensionToMime.set("ico", "image/x-icon");
    129         extensionToMime.set("js", "text/javascript");
    130     }
    131     int dot = file.reverseFind('.');
    132     String mime("text/plain");
    133     if (dot != -1) {
    134         String ext = file.substring(dot + 1);
    135         if (extensionToMime.contains(ext))
    136             mime = extensionToMime.get(ext);
    137     }
    138     return mime;
    139 }
    140 
    141 void MyResourceLoader::loadFile(const String& file)
    142 {
    143     LOGD("Loading file (%s) ...", file.latin1().data());
    144     FILE* f = fopen(file.latin1().data(), "r");
    145     ResourceHandleClient* client = m_handle->client();
    146     if (!f) {
    147         client->didFail(m_handle,
    148                 ResourceError("", -14, file, "Could not open file"));
    149     } else {
    150         ResourceResponse response;
    151         response.setTextEncodingName("utf-8");
    152         response.setMimeType(mimeTypeForExtension(file));
    153         client->didReceiveResponse(m_handle, response);
    154         char buf[512];
    155         while (true) {
    156             int res = fread(buf, 1, sizeof(buf), f);
    157             if (res <= 0)
    158                 break;
    159             client->didReceiveData(m_handle, buf, res, 0);
    160         }
    161         fclose(f);
    162         client->didFinishLoading(m_handle);
    163     }
    164 }
    165 
    166 PassRefPtr<WebCore::ResourceLoaderAndroid> MyWebFrame::startLoadingResource(
    167         ResourceHandle* handle, const ResourceRequest& req, bool ignore,
    168         bool ignore2)
    169 {
    170     RefPtr<WebCore::ResourceLoaderAndroid> loader =
    171             MyResourceLoader::create(handle, req.url().string());
    172     m_requests.append(loader);
    173     if (!m_timer.isActive())
    174         m_timer.startOneShot(0);
    175     return loader.release();
    176 }
    177 
    178 void MyWebFrame::timerFired(Timer<MyWebFrame>*)
    179 {
    180     LOGD("Handling requests...");
    181     Vector<RefPtr<WebCore::ResourceLoaderAndroid> > reqs;
    182     reqs.swap(m_requests);
    183     Vector<RefPtr<WebCore::ResourceLoaderAndroid> >::iterator i = reqs.begin();
    184     Vector<RefPtr<WebCore::ResourceLoaderAndroid> >::iterator end = reqs.end();
    185     for (; i != end; i++)
    186         static_cast<MyResourceLoader*>((*i).get())->handleRequest();
    187 
    188     LOGD("...done");
    189 }
    190