1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
19import android.graphics.Bitmap;
20
21import java.net.MalformedURLException;
22import java.net.URL;
23
24/* package */ class WebHistoryItemClassic extends WebHistoryItem implements Cloneable {
25    // Global identifier count.
26    private static int sNextId = 0;
27    // Unique identifier.
28    private final int mId;
29    // A point to a native WebHistoryItem instance which contains the actual data
30    private int mNativeBridge;
31    // The favicon for this item.
32    private Bitmap mFavicon;
33    // The pre-flattened data used for saving the state.
34    private byte[] mFlattenedData;
35    // The apple-touch-icon url for use when adding the site to the home screen,
36    // as obtained from a <link> element in the page.
37    private String mTouchIconUrlFromLink;
38    // If no <link> is specified, this holds the default location of the
39    // apple-touch-icon.
40    private String mTouchIconUrlServerDefault;
41    // Custom client data that is not flattened or read by native code.
42    private Object mCustomData;
43
44    /**
45     * Basic constructor that assigns a unique id to the item. Called by JNI
46     * only.
47     */
48    private WebHistoryItemClassic(int nativeBridge) {
49        synchronized (WebHistoryItemClassic.class) {
50            mId = sNextId++;
51        }
52        mNativeBridge = nativeBridge;
53        nativeRef(mNativeBridge);
54    }
55
56    protected void finalize() throws Throwable {
57        if (mNativeBridge != 0) {
58            nativeUnref(mNativeBridge);
59            mNativeBridge = 0;
60        }
61    }
62
63    /**
64     * Construct a new WebHistoryItem with initial flattened data.
65     * @param data The pre-flattened data coming from restoreState.
66     */
67    /*package*/ WebHistoryItemClassic(byte[] data) {
68        mFlattenedData = data;
69        synchronized (WebHistoryItemClassic.class) {
70            mId = sNextId++;
71        }
72    }
73
74    /**
75     * Construct a clone of a WebHistoryItem from the given item.
76     * @param item The history item to clone.
77     */
78    private WebHistoryItemClassic(WebHistoryItemClassic item) {
79        mFlattenedData = item.mFlattenedData;
80        mId = item.mId;
81        mFavicon = item.mFavicon;
82        mNativeBridge = item.mNativeBridge;
83        if (mNativeBridge != 0) {
84            nativeRef(mNativeBridge);
85        }
86    }
87
88    @Deprecated
89    public int getId() {
90        return mId;
91    }
92
93    public String getUrl() {
94        if (mNativeBridge == 0) return null;
95        return nativeGetUrl(mNativeBridge);
96    }
97
98    public String getOriginalUrl() {
99        if (mNativeBridge == 0) return null;
100        return nativeGetOriginalUrl(mNativeBridge);
101    }
102
103    public String getTitle() {
104        if (mNativeBridge == 0) return null;
105        return nativeGetTitle(mNativeBridge);
106    }
107
108    public Bitmap getFavicon() {
109        if (mFavicon == null && mNativeBridge != 0) {
110            mFavicon = nativeGetFavicon(mNativeBridge);
111        }
112        return mFavicon;
113    }
114
115    /**
116     * Return the touch icon url.
117     * If no touch icon <link> tag was specified, returns
118     * <host>/apple-touch-icon.png. The DownloadTouchIcon class that
119     * attempts to retrieve the touch icon will handle the case where
120     * that file does not exist. An icon set by a <link> tag is always
121     * used in preference to an icon saved on the server.
122     * @hide
123     */
124    public String getTouchIconUrl() {
125        if (mTouchIconUrlFromLink != null) {
126            return mTouchIconUrlFromLink;
127        } else if (mTouchIconUrlServerDefault != null) {
128            return mTouchIconUrlServerDefault;
129        }
130
131        try {
132            URL url = new URL(getOriginalUrl());
133            mTouchIconUrlServerDefault = new URL(url.getProtocol(), url.getHost(), url.getPort(),
134                    "/apple-touch-icon.png").toString();
135        } catch (MalformedURLException e) {
136            return null;
137        }
138        return mTouchIconUrlServerDefault;
139    }
140
141    /**
142     * Return the custom data provided by the client.
143     * @hide
144     */
145    public Object getCustomData() {
146        return mCustomData;
147    }
148
149    /**
150     * Set the custom data field.
151     * @param data An Object containing any data the client wishes to associate
152     *             with the item.
153     * @hide
154     */
155    public void setCustomData(Object data) {
156        // NOTE: WebHistoryItems are used in multiple threads. However, the
157        // public facing apis are all getters with the exception of this one
158        // api. Since this api is exclusive to clients, we don't make any
159        // promises about thread safety.
160        mCustomData = data;
161    }
162
163    /**
164     * Set the favicon.
165     * @param icon A Bitmap containing the favicon for this history item.
166     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
167     * to synchronize this method.
168     */
169    /*package*/ void setFavicon(Bitmap icon) {
170        mFavicon = icon;
171    }
172
173    /**
174     * Set the touch icon url. Will not overwrite an icon that has been
175     * set already from a <link> tag, unless the new icon is precomposed.
176     * @hide
177     */
178    /*package*/ void setTouchIconUrl(String url, boolean precomposed) {
179        if (precomposed || mTouchIconUrlFromLink == null) {
180            mTouchIconUrlFromLink = url;
181        }
182    }
183
184    /**
185     * Get the pre-flattened data.
186     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
187     * to synchronize this method.
188     */
189    /*package*/ byte[] getFlattenedData() {
190        if (mNativeBridge != 0) {
191            return nativeGetFlattenedData(mNativeBridge);
192        }
193        return mFlattenedData;
194    }
195
196    /**
197     * Inflate this item.
198     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
199     * to synchronize this method.
200     */
201    /*package*/ void inflate(int nativeFrame) {
202        mNativeBridge = inflate(nativeFrame, mFlattenedData);
203        mFlattenedData = null;
204    }
205
206    public synchronized WebHistoryItemClassic clone() {
207        return new WebHistoryItemClassic(this);
208    }
209
210    /* Natively inflate this item, this method is called in the WebCore thread.
211     */
212    private native int inflate(int nativeFrame, byte[] data);
213    private native void nativeRef(int nptr);
214    private native void nativeUnref(int nptr);
215    private native String nativeGetTitle(int nptr);
216    private native String nativeGetUrl(int nptr);
217    private native String nativeGetOriginalUrl(int nptr);
218    private native byte[] nativeGetFlattenedData(int nptr);
219    private native Bitmap nativeGetFavicon(int nptr);
220
221}
222