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 17 package android.webkit; 18 19 import java.io.Serializable; 20 import java.util.ArrayList; 21 22 /* package */ class WebBackForwardListClassic extends WebBackForwardList implements Cloneable, 23 Serializable { 24 25 // Current position in the list. 26 private int mCurrentIndex; 27 // ArrayList of WebHistoryItems for maintaining our copy. 28 private ArrayList<WebHistoryItemClassic> mArray; 29 // Flag to indicate that the list is invalid 30 private boolean mClearPending; 31 // CallbackProxy to issue client callbacks. 32 private final CallbackProxy mCallbackProxy; 33 WebBackForwardListClassic(CallbackProxy proxy)34 /*package*/ WebBackForwardListClassic(CallbackProxy proxy) { 35 mCurrentIndex = -1; 36 mArray = new ArrayList<WebHistoryItemClassic>(); 37 mCallbackProxy = proxy; 38 } 39 getCurrentItem()40 public synchronized WebHistoryItemClassic getCurrentItem() { 41 return getItemAtIndex(mCurrentIndex); 42 } 43 getCurrentIndex()44 public synchronized int getCurrentIndex() { 45 return mCurrentIndex; 46 } 47 getItemAtIndex(int index)48 public synchronized WebHistoryItemClassic getItemAtIndex(int index) { 49 if (index < 0 || index >= getSize()) { 50 return null; 51 } 52 return mArray.get(index); 53 } 54 getSize()55 public synchronized int getSize() { 56 return mArray.size(); 57 } 58 59 /** 60 * Mark the back/forward list as having a pending clear. This is used on the 61 * UI side to mark the list as being invalid during the clearHistory method. 62 */ setClearPending()63 /*package*/ synchronized void setClearPending() { 64 mClearPending = true; 65 } 66 67 /** 68 * Return the status of the clear flag. This is used on the UI side to 69 * determine if the list is valid for checking things like canGoBack. 70 */ getClearPending()71 /*package*/ synchronized boolean getClearPending() { 72 return mClearPending; 73 } 74 75 /** 76 * Add a new history item to the list. This will remove all items after the 77 * current item and append the new item to the end of the list. Called from 78 * the WebCore thread only. Synchronized because the UI thread may be 79 * reading the array or the current index. 80 * @param item A new history item. 81 */ addHistoryItem(WebHistoryItem item)82 /*package*/ synchronized void addHistoryItem(WebHistoryItem item) { 83 // Update the current position because we are going to add the new item 84 // in that slot. 85 ++mCurrentIndex; 86 // If the current position is not at the end, remove all history items 87 // after the current item. 88 final int size = mArray.size(); 89 final int newPos = mCurrentIndex; 90 if (newPos != size) { 91 for (int i = size - 1; i >= newPos; i--) { 92 final WebHistoryItem h = mArray.remove(i); 93 } 94 } 95 // Add the item to the list. 96 mArray.add((WebHistoryItemClassic) item); 97 if (mCallbackProxy != null) { 98 mCallbackProxy.onNewHistoryItem(item); 99 } 100 } 101 102 /** 103 * Clear the back/forward list. Called from the WebCore thread. 104 */ close(int nativeFrame)105 /*package*/ synchronized void close(int nativeFrame) { 106 // Clear the array first because nativeClose will call addHistoryItem 107 // with the current item. 108 mArray.clear(); 109 mCurrentIndex = -1; 110 nativeClose(nativeFrame); 111 // Reset the clear flag 112 mClearPending = false; 113 } 114 115 /* Remove the item at the given index. Called by JNI only. */ removeHistoryItem(int index)116 private synchronized void removeHistoryItem(int index) { 117 // XXX: This is a special case. Since the callback is only triggered 118 // when removing the first item, we can assert that the index is 0. 119 // This lets us change the current index without having to query the 120 // native BackForwardList. 121 if (DebugFlags.WEB_BACK_FORWARD_LIST && (index != 0)) { 122 throw new AssertionError(); 123 } 124 final WebHistoryItem h = mArray.remove(index); 125 // XXX: If we ever add another callback for removing history items at 126 // any index, this will no longer be valid. 127 mCurrentIndex--; 128 } 129 clone()130 public synchronized WebBackForwardListClassic clone() { 131 WebBackForwardListClassic l = new WebBackForwardListClassic(null); 132 if (mClearPending) { 133 // If a clear is pending, return a copy with only the current item. 134 l.addHistoryItem(getCurrentItem()); 135 return l; 136 } 137 l.mCurrentIndex = mCurrentIndex; 138 int size = getSize(); 139 l.mArray = new ArrayList<WebHistoryItemClassic>(size); 140 for (int i = 0; i < size; i++) { 141 // Add a copy of each WebHistoryItem 142 l.mArray.add(mArray.get(i).clone()); 143 } 144 return l; 145 } 146 147 /** 148 * Set the new history index. 149 * @param newIndex The new history index. 150 */ setCurrentIndex(int newIndex)151 /*package*/ synchronized void setCurrentIndex(int newIndex) { 152 mCurrentIndex = newIndex; 153 if (mCallbackProxy != null) { 154 mCallbackProxy.onIndexChanged(getItemAtIndex(newIndex), newIndex); 155 } 156 } 157 158 /** 159 * Restore the history index. 160 */ restoreIndex(int nativeFrame, int index)161 /*package*/ static native synchronized void restoreIndex(int nativeFrame, 162 int index); 163 164 /* Close the native list. */ nativeClose(int nativeFrame)165 private static native void nativeClose(int nativeFrame); 166 } 167