/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.webkit; import android.net.http.Headers; import java.io.InputStream; import java.util.*; import org.apache.http.util.CharArrayBuffer; /** * This class is a concrete implementation of StreamLoader that uses a * PluginData object as the source for the stream. */ class PluginContentLoader extends StreamLoader { private PluginData mData; // Content source /** * Constructs a PluginDataLoader for use when loading content from * a plugin. * * @param loadListener LoadListener to pass the content to * @param data PluginData used as the source for the content. */ PluginContentLoader(LoadListener loadListener, PluginData data) { super(loadListener); mData = data; } @Override protected boolean setupStreamAndSendStatus() { mDataStream = mData.getInputStream(); mContentLength = mData.getContentLength(); mHandler.status(1, 1, mData.getStatusCode(), "OK"); return true; } @Override protected void buildHeaders(Headers headers) { // Crate a CharArrayBuffer with an arbitrary initial capacity. CharArrayBuffer buffer = new CharArrayBuffer(100); Iterator<Map.Entry<String, String[]>> responseHeadersIt = mData.getHeaders().entrySet().iterator(); while (responseHeadersIt.hasNext()) { Map.Entry<String, String[]> entry = responseHeadersIt.next(); // Headers.parseHeader() expects lowercase keys, so keys // such as "Accept-Ranges" will fail to parse. // // UrlInterceptHandler instances supply a mapping of // lowercase key to [ unmodified key, value ], so for // Headers.parseHeader() to succeed, we need to construct // a string using the key (i.e. entry.getKey()) and the // element denoting the header value in the // [ unmodified key, value ] pair (i.e. entry.getValue()[1). // // The reason why UrlInterceptHandler instances supply such a // mapping in the first place is historical. Early versions of // the Gears plugin used java.net.HttpURLConnection, which always // returned headers names as capitalized strings. When these were // fed back into webkit, they failed to parse. // // Mewanwhile, Gears was modified to use Apache HTTP library // instead, so this design is now obsolete. Changing it however, // would require changes to the Gears C++ codebase and QA-ing and // submitting a new binary to the Android tree. Given the // timelines for the next Android release, we will not do this // for now. // // TODO: fix C++ Gears to remove the need for this // design. String keyValue = entry.getKey() + ": " + entry.getValue()[1]; buffer.ensureCapacity(keyValue.length()); buffer.append(keyValue); // Parse it into the header container. headers.parseHeader(buffer); // Clear the buffer buffer.clear(); } } }