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 "HTTPParsers.h"
     31 #include "Intercept.h"
     32 #include "ResourceHandle.h"
     33 #include "ResourceHandleClient.h"
     34 #include "ResourceRequest.h"
     35 #include "ResourceResponse.h"
     36 #include "TextEncoding.h"
     37 
     38 #include <utils/Log.h>
     39 #include <wtf/HashMap.h>
     40 #include <wtf/text/CString.h>
     41 #include <wtf/text/StringHash.h>
     42 
     43 PassRefPtr<WebCore::ResourceLoaderAndroid> MyResourceLoader::create(
     44         ResourceHandle* handle, String url)
     45 {
     46     return adoptRef<WebCore::ResourceLoaderAndroid>(
     47             new MyResourceLoader(handle, url));
     48 }
     49 
     50 void MyResourceLoader::handleRequest()
     51 {
     52     if (protocolIs(m_url, "data"))
     53         loadData(m_url.substring(5)); // 5 for data:
     54     else if (protocolIs(m_url, "file"))
     55         loadFile(m_url.substring(7)); // 7 for file://
     56 }
     57 
     58 void MyResourceLoader::loadData(const String& data)
     59 {
     60     LOGD("Loading data (%s) ...", data.latin1().data());
     61     ResourceHandleClient* client = m_handle->client();
     62     int index = data.find(',');
     63     if (index == -1) {
     64         client->cannotShowURL(m_handle);
     65         return;
     66     }
     67 
     68     String mediaType = data.substring(0, index);
     69     String base64 = data.substring(index + 1);
     70 
     71     bool decode = mediaType.endsWith(";base64", false);
     72     if (decode)
     73         mediaType = mediaType.left(mediaType.length() - 7); // 7 for base64;
     74 
     75     if (mediaType.isEmpty())
     76         mediaType = "text/plain;charset=US-ASCII";
     77 
     78     String mimeType = extractMIMETypeFromMediaType(mediaType);
     79     String charset = extractCharsetFromMediaType(mediaType);
     80 
     81     ResourceResponse response;
     82     response.setMimeType(mimeType);
     83 
     84     if (decode) {
     85         base64 = decodeURLEscapeSequences(base64);
     86         response.setTextEncodingName(charset);
     87         client->didReceiveResponse(m_handle, response);
     88 
     89         // FIXME: This is annoying. WebCore's Base64 decoder chokes on spaces.
     90         // That is correct with strict decoding but html authors (particularly
     91         // the acid3 authors) put spaces in the data which should be ignored.
     92         // Remove them here before sending to the decoder.
     93         Vector<char> in;
     94         CString str = base64.latin1();
     95         const char* chars = str.data();
     96         unsigned i = 0;
     97         while (i < str.length()) {
     98             char c = chars[i];
     99             // Don't send spaces or control characters.
    100             if (c != ' ' && c != '\n' && c != '\t' && c != '\b'
    101                     && c != '\f' && c != '\r')
    102                 in.append(chars[i]);
    103             i++;
    104         }
    105         Vector<char> out;
    106         if (base64Decode(in, out) && out.size() > 0)
    107             client->didReceiveData(m_handle, out.data(), out.size(), 0);
    108     } else {
    109         base64 = decodeURLEscapeSequences(base64, TextEncoding(charset));
    110         response.setTextEncodingName("UTF-16");
    111         client->didReceiveResponse(m_handle, response);
    112         if (base64.length() > 0)
    113             client->didReceiveData(m_handle, (const char*)base64.characters(),
    114                     base64.length() * sizeof(UChar), 0);
    115     }
    116     client->didFinishLoading(m_handle, 0);
    117 }
    118 static String mimeTypeForExtension(const String& file)
    119 {
    120     static HashMap<String, String, CaseFoldingHash> extensionToMime;
    121     if (extensionToMime.isEmpty()) {
    122         extensionToMime.set("txt", "text/plain");
    123         extensionToMime.set("html", "text/html");
    124         extensionToMime.set("htm", "text/html");
    125         extensionToMime.set("png", "image/png");
    126         extensionToMime.set("jpeg", "image/jpeg");
    127         extensionToMime.set("jpg", "image/jpeg");
    128         extensionToMime.set("gif", "image/gif");
    129         extensionToMime.set("ico", "image/x-icon");
    130         extensionToMime.set("js", "text/javascript");
    131     }
    132     int dot = file.reverseFind('.');
    133     String mime("text/plain");
    134     if (dot != -1) {
    135         String ext = file.substring(dot + 1);
    136         if (extensionToMime.contains(ext))
    137             mime = extensionToMime.get(ext);
    138     }
    139     return mime;
    140 }
    141 
    142 void MyResourceLoader::loadFile(const String& file)
    143 {
    144     LOGD("Loading file (%s) ...", file.latin1().data());
    145     FILE* f = fopen(file.latin1().data(), "r");
    146     ResourceHandleClient* client = m_handle->client();
    147     if (!f) {
    148         client->didFail(m_handle,
    149                 ResourceError("", -14, file, "Could not open file"));
    150     } else {
    151         ResourceResponse response;
    152         response.setTextEncodingName("utf-8");
    153         response.setMimeType(mimeTypeForExtension(file));
    154         client->didReceiveResponse(m_handle, response);
    155         char buf[512];
    156         while (true) {
    157             int res = fread(buf, 1, sizeof(buf), f);
    158             if (res <= 0)
    159                 break;
    160             client->didReceiveData(m_handle, buf, res, 0);
    161         }
    162         fclose(f);
    163         client->didFinishLoading(m_handle, 0);
    164     }
    165 }
    166 
    167 PassRefPtr<WebCore::ResourceLoaderAndroid> MyWebFrame::startLoadingResource(
    168         ResourceHandle* handle, const ResourceRequest& req, bool ignore,
    169         bool ignore2)
    170 {
    171     RefPtr<WebCore::ResourceLoaderAndroid> loader =
    172             MyResourceLoader::create(handle, req.url().string());
    173     m_requests.append(loader);
    174     if (!m_timer.isActive())
    175         m_timer.startOneShot(0);
    176     return loader.release();
    177 }
    178 
    179 void MyWebFrame::timerFired(Timer<MyWebFrame>*)
    180 {
    181     LOGD("Handling requests...");
    182     Vector<RefPtr<WebCore::ResourceLoaderAndroid> > reqs;
    183     reqs.swap(m_requests);
    184     Vector<RefPtr<WebCore::ResourceLoaderAndroid> >::iterator i = reqs.begin();
    185     Vector<RefPtr<WebCore::ResourceLoaderAndroid> >::iterator end = reqs.end();
    186     for (; i != end; i++)
    187         static_cast<MyResourceLoader*>((*i).get())->handleRequest();
    188 
    189     LOGD("...done");
    190 }
    191