/*
 * Copyright (C) 2006 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.ErrorStrings;
import android.net.http.EventHandler;
import android.net.http.RequestHandle;
import android.os.Build;
import android.util.Log;
import android.webkit.CacheManager.CacheResult;
import android.webkit.JniUtil;

import java.util.HashMap;
import java.util.Map;

class FrameLoader {

    private final LoadListener mListener;
    private final String mMethod;
    private final WebSettings mSettings;
    private Map<String, String> mHeaders;
    private byte[] mPostData;
    private Network mNetwork;
    private int mCacheMode;
    private String mReferrer;
    private String mContentType;
    private final String mUaprofHeader;
    private final WebResourceResponse mInterceptResponse;

    private static final int URI_PROTOCOL = 0x100;

    private static final String CONTENT_TYPE = "content-type";

    // Contents of an about:blank page
    private static final String mAboutBlank =
            "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EB\">" +
            "<html><head><title>about:blank</title></head><body></body></html>";

    static final String HEADER_STR = "text/xml, text/html, " +
            "application/xhtml+xml, image/png, text/plain, */*;q=0.8";

    private static final String LOGTAG = "webkit";
    
    FrameLoader(LoadListener listener, WebSettings settings,
            String method, WebResourceResponse interceptResponse) {
        assert !JniUtil.useChromiumHttpStack();

        mListener = listener;
        mHeaders = null;
        mMethod = method;
        mCacheMode = WebSettings.LOAD_NORMAL;
        mSettings = settings;
        mInterceptResponse = interceptResponse;
        mUaprofHeader = mListener.getContext().getResources().getString(
                com.android.internal.R.string.config_useragentprofile_url, Build.MODEL);
    }

    public void setReferrer(String ref) {
        // only set referrer for http or https
        if (URLUtil.isNetworkUrl(ref)) mReferrer = ref;
    }

    public void setPostData(byte[] postData) {
        mPostData = postData;
    }

    public void setContentTypeForPost(String postContentType) {
        mContentType = postContentType;
    }

    public void setCacheMode(int cacheMode) {
        mCacheMode = cacheMode;
    }

    public void setHeaders(HashMap headers) {
        mHeaders = headers;
    }

    public LoadListener getLoadListener() {
        return mListener;
    }

    /**
     * Issues the load request.
     *
     * Return value does not indicate if the load was successful or not. It
     * simply indicates that the load request is reasonable.
     *
     * @return true if the load is reasonable.
     */
    public boolean executeLoad() {
        String url = mListener.url();

        // Process intercepted requests first as they could be any url.
        if (mInterceptResponse != null) {
            if (mListener.isSynchronous()) {
                mInterceptResponse.loader(mListener).load();
            } else {
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_ADD_STREAMLOADER,
                        mInterceptResponse.loader(mListener)).sendToTarget();
            }
            return true;
        } else if (URLUtil.isNetworkUrl(url)){
            if (mSettings.getBlockNetworkLoads()) {
                mListener.error(EventHandler.ERROR_BAD_URL,
                        mListener.getContext().getString(
                                com.android.internal.R.string.httpErrorBadUrl));
                return false;
            }
            // Make sure the host part of the url is correctly
            // encoded before sending the request
            if (!URLUtil.verifyURLEncoding(mListener.host())) {
                mListener.error(EventHandler.ERROR_BAD_URL,
                        mListener.getContext().getString(
                        com.android.internal.R.string.httpErrorBadUrl));
                return false;
            }
            mNetwork = Network.getInstance(mListener.getContext());
            if (mListener.isSynchronous()) {
                return handleHTTPLoad();
            }
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_ADD_HTTPLOADER, this).sendToTarget();
            return true;
        } else if (handleLocalFile(url, mListener, mSettings)) {
            return true;
        }
        if (DebugFlags.FRAME_LOADER) {
            Log.v(LOGTAG, "FrameLoader.executeLoad: url protocol not supported:"
                    + mListener.url());
        }
        mListener.error(EventHandler.ERROR_UNSUPPORTED_SCHEME,
                mListener.getContext().getText(
                        com.android.internal.R.string.httpErrorUnsupportedScheme).toString());
        return false;

    }

    private static boolean handleLocalFile(String url, LoadListener loadListener,
            WebSettings settings) {
        assert !JniUtil.useChromiumHttpStack();

        // Attempt to decode the percent-encoded url before passing to the
        // local loaders.
        try {
            url = new String(URLUtil.decode(url.getBytes()));
        } catch (IllegalArgumentException e) {
            loadListener.error(EventHandler.ERROR_BAD_URL,
                    loadListener.getContext().getString(
                            com.android.internal.R.string.httpErrorBadUrl));
            // Return true here so we do not trigger an unsupported scheme
            // error.
            return true;
        }
        if (URLUtil.isAssetUrl(url)) {
            if (loadListener.isSynchronous()) {
                new FileLoader(url, loadListener, FileLoader.TYPE_ASSET,
                        true).load();
            } else {
                // load asset in a separate thread as it involves IO
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_ADD_STREAMLOADER,
                        new FileLoader(url, loadListener, FileLoader.TYPE_ASSET,
                                true)).sendToTarget();
            }
            return true;
        } else if (URLUtil.isResourceUrl(url)) {
            if (loadListener.isSynchronous()) {
                new FileLoader(url, loadListener, FileLoader.TYPE_RES,
                        true).load();
            } else {
                // load resource in a separate thread as it involves IO
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_ADD_STREAMLOADER,
                        new FileLoader(url, loadListener, FileLoader.TYPE_RES,
                                true)).sendToTarget();
            }
            return true;
        } else if (URLUtil.isFileUrl(url)) {
            if (loadListener.isSynchronous()) {
                new FileLoader(url, loadListener, FileLoader.TYPE_FILE,
                        settings.getAllowFileAccess()).load();
            } else {
                // load file in a separate thread as it involves IO
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_ADD_STREAMLOADER,
                        new FileLoader(url, loadListener, FileLoader.TYPE_FILE,
                                settings.getAllowFileAccess())).sendToTarget();
            }
            return true;
        } else if (settings.getAllowContentAccess() &&
                   URLUtil.isContentUrl(url)) {
            // Send the raw url to the ContentLoader because it will do a
            // permission check and the url has to match.
            if (loadListener.isSynchronous()) {
                new ContentLoader(loadListener.url(), loadListener).load();
            } else {
                // load content in a separate thread as it involves IO
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_ADD_STREAMLOADER,
                        new ContentLoader(loadListener.url(), loadListener))
                        .sendToTarget();
            }
            return true;
        } else if (URLUtil.isDataUrl(url)) {
            // load data in the current thread to reduce the latency
            new DataLoader(url, loadListener).load();
            return true;
        } else if (URLUtil.isAboutUrl(url)) {
            loadListener.data(mAboutBlank.getBytes(), mAboutBlank.length());
            loadListener.endData();
            return true;
        }
        return false;
    }

    boolean handleHTTPLoad() {
        if (mHeaders == null) {
            mHeaders = new HashMap<String, String>();
        }
        populateStaticHeaders();
        populateHeaders();

        // response was handled by Cache, don't issue HTTP request
        if (handleCache()) {
            // push the request data down to the LoadListener
            // as response from the cache could be a redirect
            // and we may need to initiate a network request if the cache
            // can't satisfy redirect URL
            mListener.setRequestData(mMethod, mHeaders, mPostData);
            return true;
        }

        if (DebugFlags.FRAME_LOADER) {
            Log.v(LOGTAG, "FrameLoader: http " + mMethod + " load for: "
                    + mListener.url());
        }

        boolean ret = false;
        int error = EventHandler.ERROR_UNSUPPORTED_SCHEME;
        
        try {
            ret = mNetwork.requestURL(mMethod, mHeaders,
                    mPostData, mListener);
        } catch (android.net.ParseException ex) {
            error = EventHandler.ERROR_BAD_URL;
        } catch (java.lang.RuntimeException ex) {
            /* probably an empty header set by javascript.  We want
               the same result as bad URL  */
            error = EventHandler.ERROR_BAD_URL;
        }
        if (!ret) {
            mListener.error(error, ErrorStrings.getString(error, mListener.getContext()));
            return false;
        }
        return true;
    }

    /*
     * This function is used by handleCache to
     * setup a load from the byte stream in a CacheResult.
     */
    private void startCacheLoad(CacheResult result) {
        if (DebugFlags.FRAME_LOADER) {
            Log.v(LOGTAG, "FrameLoader: loading from cache: "
                  + mListener.url());
        }
        // Tell the Listener respond with the cache file
        CacheLoader cacheLoader =
                new CacheLoader(mListener, result);
        mListener.setCacheLoader(cacheLoader);
        if (mListener.isSynchronous()) {
            cacheLoader.load();
        } else {
            // Load the cached file in a separate thread
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_ADD_STREAMLOADER, cacheLoader).sendToTarget();
        }
    }

    /*
     * This function is used by the handleHTTPLoad to setup the cache headers
     * correctly.
     * Returns true if the response was handled from the cache
     */
    private boolean handleCache() {
        switch (mCacheMode) {
            // This mode is normally used for a reload, it instructs the http
            // loader to not use the cached content.
            case WebSettings.LOAD_NO_CACHE:
                break;
                
                
            // This mode is used when the content should only be loaded from
            // the cache. If it is not there, then fail the load. This is used
            // to load POST content in a history navigation.
            case WebSettings.LOAD_CACHE_ONLY: {
                CacheResult result = CacheManager.getCacheFile(mListener.url(),
                        mListener.postIdentifier(), null);
                if (result != null) {
                    startCacheLoad(result);
                } else {
                    // This happens if WebCore was first told that the POST
                    // response was in the cache, then when we try to use it
                    // it has gone.
                    // Generate a file not found error
                    int err = EventHandler.FILE_NOT_FOUND_ERROR;
                    mListener.error(err,
                            ErrorStrings.getString(err, mListener.getContext()));
                }
                return true;
            }

            // This mode is for when the user is doing a history navigation
            // in the browser and should returned cached content regardless
            // of it's state. If it is not in the cache, then go to the 
            // network.
            case WebSettings.LOAD_CACHE_ELSE_NETWORK: {
                if (DebugFlags.FRAME_LOADER) {
                    Log.v(LOGTAG, "FrameLoader: checking cache: "
                            + mListener.url());
                }
                // Get the cache file name for the current URL, passing null for
                // the validation headers causes no validation to occur
                CacheResult result = CacheManager.getCacheFile(mListener.url(),
                        mListener.postIdentifier(), null);
                if (result != null) {
                    startCacheLoad(result);
                    return true;
                }
                break;
            }

            // This is the default case, which is to check to see if the
            // content in the cache can be used. If it can be used, then
            // use it. If it needs revalidation then the relevant headers
            // are added to the request.
            default:
            case WebSettings.LOAD_NORMAL:
                return mListener.checkCache(mHeaders);
        }// end of switch

        return false;
    }
    
    /**
     * Add the static headers that don't change with each request.
     */
    private void populateStaticHeaders() {
        // Accept header should already be there as they are built by WebCore,
        // but in the case they are missing, add some.
        String accept = mHeaders.get("Accept");
        if (accept == null || accept.length() == 0) {
            mHeaders.put("Accept", HEADER_STR);
        }
        mHeaders.put("Accept-Charset", "utf-8, iso-8859-1, utf-16, *;q=0.7");

        String acceptLanguage = mSettings.getAcceptLanguage();
        if (acceptLanguage.length() > 0) {
            mHeaders.put("Accept-Language", acceptLanguage);
        }
        
        mHeaders.put("User-Agent", mSettings.getUserAgentString());

        // Set the x-wap-profile header
        if (mUaprofHeader != null && mUaprofHeader.length() > 0) {
            mHeaders.put("x-wap-profile", mUaprofHeader);
        }
    }

    /**
     * Add the content related headers. These headers contain user private data
     * and is not used when we are proxying an untrusted request.
     */
    private void populateHeaders() {
        
        if (mReferrer != null) mHeaders.put("Referer", mReferrer);
        if (mContentType != null) mHeaders.put(CONTENT_TYPE, mContentType);

        // if we have an active proxy and have proxy credentials, do pre-emptive
        // authentication to avoid an extra round-trip:
        if (mNetwork.isValidProxySet()) {
            String username;
            String password;
            /* The proxy credentials can be set in the Network thread */
            synchronized (mNetwork) {
                username = mNetwork.getProxyUsername();
                password = mNetwork.getProxyPassword();
            }
            if (username != null && password != null) {
                // we collect credentials ONLY if the proxy scheme is BASIC!!!
                String proxyHeader = RequestHandle.authorizationHeader(true);
                mHeaders.put(proxyHeader,
                        "Basic " + RequestHandle.computeBasicAuthResponse(
                                username, password));
            }
        }

        // Set cookie header
        String cookie = CookieManager.getInstance().getCookie(
                mListener.getWebAddress());
        if (cookie != null && cookie.length() > 0) {
            mHeaders.put("Cookie", cookie);
        }
    }
}
