18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright 2007, The Android Open Source Project
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  * Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
163298a7d84b96ade73c6b170671711a8f2792ae59Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define LOG_TAG "webhistory"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2820ab751acc0d49d74648373f701f3d0c4ff187c0Steve Block#include "config.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebHistory.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
31e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck#include "AndroidLog.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "BackForwardList.h"
33d0dada9ef392026973da2fbb2cb4d9b9504f91f0Teng-Hui Zhu#include "BackForwardListImpl.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DocumentLoader.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameLoader.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameLoaderClientAndroid.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameTree.h"
39e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck#include "GraphicsJNI.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HistoryItem.h"
41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "IconDatabase.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Page.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextEncoding.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebCoreFrameBridge.h"
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebCoreJni.h"
4694f369b3daaa736ae6488f8f206884d0dcf600aaPatrick Scott#include "WebIconDatabase.h"
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <JNIHelp.h>
4920ab751acc0d49d74648373f701f3d0c4ff187c0Steve Block#include "JNIUtility.h"
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <SkUtils.h>
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <utils/misc.h>
5220ab751acc0d49d74648373f701f3d0c4ff187c0Steve Block#include <wtf/OwnPtr.h>
5320ab751acc0d49d74648373f701f3d0c4ff187c0Steve Block#include <wtf/Platform.h>
5479768700a853c40c66ff0b0591957958667fdd9eSteve Block#include <wtf/text/CString.h>
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace android {
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Forward declarations
59c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brennerstatic void writeItem(WTF::Vector<char>& vector, WebCore::HistoryItem* item);
60c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brennerstatic void writeChildrenRecursive(WTF::Vector<char>& vector, WebCore::HistoryItem* parent);
61c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brennerstatic bool readItemRecursive(WebCore::HistoryItem* child, const char** pData, int length);
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Field ids for WebHistoryItems
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct WebHistoryItemFields {
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jmethodID   mInit;
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} gWebHistoryItem;
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct WebBackForwardListFields {
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jmethodID   mAddHistoryItem;
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jmethodID   mRemoveHistoryItem;
71730ce864fef32412598ac6b1f5e48a02f217ca25Patrick Scott    jmethodID   mSetCurrentIndex;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} gWebBackForwardList;
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project//--------------------------------------------------------------------------
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// WebBackForwardList native methods.
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project//--------------------------------------------------------------------------
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void WebHistoryClose(JNIEnv* env, jobject obj, jint frame)
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
806dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(frame, "Close needs a valid Frame pointer!");
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::Frame* pFrame = (WebCore::Frame*)frame;
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
83d0dada9ef392026973da2fbb2cb4d9b9504f91f0Teng-Hui Zhu    WebCore::BackForwardListImpl* list = static_cast<WebCore::BackForwardListImpl*>(pFrame->page()->backForwardList());
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<WebCore::HistoryItem> current = list->currentItem();
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Remove each item instead of using close(). close() is intended to be used
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // right before the list is deleted.
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::HistoryItemVector& entries = list->entries();
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int size = entries.size();
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (int i = size - 1; i >= 0; --i)
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        list->removeItem(entries[i].get());
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Add the current item back to the list.
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (current) {
93be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch        current->setBridge(0);
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // addItem will update the children to match the newly created bridge
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        list->addItem(current);
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        /*
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * The Grand Prix site uses anchor navigations to change the display.
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * WebKit tries to be smart and not load child frames that have the
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * same history urls during an anchor navigation. This means that the
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * current history item stored in the child frame's loader does not
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * match the item found in the history tree. If we remove all the
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * entries in the back/foward list, we have to restore the entire tree
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * or else a HistoryItem might have a deleted parent.
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         *
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * In order to restore the history tree correctly, we have to look up
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * all the frames first and then look up the history item. We do this
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * because the history item in the tree may be null at this point.
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * Unfortunately, a HistoryItem can only search its immediately
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * children so we do a breadth-first rebuild of the tree.
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         */
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Keep a small list of child frames to traverse.
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WTF::Vector<WebCore::Frame*> frameQueue;
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Fix the top-level item.
11667ed0edeb2ad5bb22ec778472b78d41e7eb3b68aSteve Block        pFrame->loader()->history()->setCurrentItem(current.get());
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WebCore::Frame* child = pFrame->tree()->firstChild();
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Remember the parent history item so we can search for a child item.
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RefPtr<WebCore::HistoryItem> parent = current;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (child) {
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Use the old history item since the current one may have a
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // deleted parent.
1235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            WebCore::HistoryItem* item = parent->childItemWithTarget(child->tree()->name());
12467ed0edeb2ad5bb22ec778472b78d41e7eb3b68aSteve Block            child->loader()->history()->setCurrentItem(item);
125db239ca3504af9998d5717708fdef4676e286602Patrick Scott            // Append the first child to the queue if it exists. If there is no
126db239ca3504af9998d5717708fdef4676e286602Patrick Scott            // item, then we do not need to traverse the children since there
127db239ca3504af9998d5717708fdef4676e286602Patrick Scott            // will be no parent history item.
128db239ca3504af9998d5717708fdef4676e286602Patrick Scott            WebCore::Frame* firstChild;
129db239ca3504af9998d5717708fdef4676e286602Patrick Scott            if (item && (firstChild = child->tree()->firstChild()))
130db239ca3504af9998d5717708fdef4676e286602Patrick Scott                frameQueue.append(firstChild);
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            child = child->tree()->nextSibling();
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If we don't have a sibling for this frame and the queue isn't
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // empty, use the next entry in the queue.
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!child && !frameQueue.isEmpty()) {
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                child = frameQueue.at(0);
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                frameQueue.remove(0);
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Figure out the parent history item used when searching for
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // the history item to use.
13967ed0edeb2ad5bb22ec778472b78d41e7eb3b68aSteve Block                parent = child->tree()->parent()->loader()->history()->currentItem();
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void WebHistoryRestoreIndex(JNIEnv* env, jobject obj, jint frame, jint index)
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1476dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(frame, "RestoreState needs a valid Frame pointer!");
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::Frame* pFrame = (WebCore::Frame*)frame;
149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    WebCore::Page* page = pFrame->page();
150fa1ac15a8417461f160824c688d94b80150f799ePatrick Scott    WebCore::HistoryItem* currentItem =
151d0dada9ef392026973da2fbb2cb4d9b9504f91f0Teng-Hui Zhu            static_cast<WebCore::BackForwardListImpl*>(page->backForwardList())->entries()[index].get();
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
153635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // load the current page with FrameLoadTypeIndexedBackForward so that it
154635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // will use cache when it is possible
155635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    page->goToItem(currentItem, FrameLoadTypeIndexedBackForward);
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
158e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reckstatic jint WebHistoryInflate(JNIEnv* env, jobject obj, jint frame, jbyteArray data)
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1606dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(frame, "Inflate needs a valid frame pointer!");
1616dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(data, "Inflate needs a valid data pointer!");
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Get the actual bytes and the length from the java array.
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const jbyte* bytes = env->GetByteArrayElements(data, NULL);
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jsize size = env->GetArrayLength(data);
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Inflate the history tree into one HistoryItem or null if the inflation
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // failed.
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<WebCore::HistoryItem> newItem = WebCore::HistoryItem::create();
170e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    WebHistoryItem* bridge = new WebHistoryItem(newItem.get());
1718c5d18443e0c51c5762b25da443b1a76c75a5d86Patrick Scott    newItem->setBridge(bridge);
172be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Inflate the item recursively. If it fails, that is ok. We'll have an
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // incomplete HistoryItem but that is better than crashing due to a null
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // item.
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We have a 2nd local variable since read_item_recursive may change the
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // ptr's value. We can't pass &bytes since we have to send bytes to
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // ReleaseByteArrayElements unchanged.
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* ptr = reinterpret_cast<const char*>(bytes);
180c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    readItemRecursive(newItem.get(), &ptr, (int)size);
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->ReleaseByteArrayElements(data, const_cast<jbyte*>(bytes), JNI_ABORT);
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bridge->setActive();
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Add the new item to the back/forward list.
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::Frame* pFrame = (WebCore::Frame*)frame;
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pFrame->page()->backForwardList()->addItem(newItem);
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Update the item.
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bridge->updateHistoryItem(newItem.get());
190e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    // Ref here because Java expects to adopt the reference, and as such will not
191e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    // call ref on it. However, setBridge has also adopted the reference
192e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    // TODO: This is confusing as hell, clean up ownership and have setBridge
193e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    // take a RefPtr instead of a raw ptr and calling adoptRef on it
194e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    bridge->ref();
195e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    return reinterpret_cast<jint>(bridge);
196e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck}
197e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
198e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reckstatic void WebHistoryRef(JNIEnv* env, jobject obj, jint ptr)
199e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck{
200e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (ptr)
201e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        reinterpret_cast<WebHistoryItem*>(ptr)->ref();
202e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck}
203e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
204e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reckstatic void WebHistoryUnref(JNIEnv* env, jobject obj, jint ptr)
205e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck{
206e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (ptr)
207e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        reinterpret_cast<WebHistoryItem*>(ptr)->deref();
208e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck}
209e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
210e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reckstatic jobject WebHistoryGetTitle(JNIEnv* env, jobject obj, jint ptr)
211e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck{
212e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (!ptr)
213e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        return 0;
214e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
215e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    MutexLocker locker(item->m_lock);
216e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    return wtfStringToJstring(env, item->m_title, false);
217e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck}
218e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
219e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reckstatic jobject WebHistoryGetUrl(JNIEnv* env, jobject obj, jint ptr)
220e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck{
221e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (!ptr)
222e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        return 0;
223e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
224e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    MutexLocker locker(item->m_lock);
225e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    return wtfStringToJstring(env, item->m_url, false);
226e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck}
227e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
228e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reckstatic jobject WebHistoryGetOriginalUrl(JNIEnv* env, jobject obj, jint ptr)
229e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck{
230e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (!ptr)
231e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        return 0;
232e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
233e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    MutexLocker locker(item->m_lock);
234e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    return wtfStringToJstring(env, item->m_originalUrl, false);
235e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck}
236e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
237e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reckstatic jobject WebHistoryGetFlattenedData(JNIEnv* env, jobject obj, jint ptr)
238e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck{
239e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (!ptr)
240e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        return 0;
241e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
242e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
243e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    MutexLocker locker(item->m_lock);
244e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
245e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (!item->m_dataCached) {
246e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        // Try to create a new java byte array.
247e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        jbyteArray b = env->NewByteArray(item->m_data.size());
248e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        if (!b)
249e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck            return NULL;
250e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
251e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        // Write our flattened data to the java array.
252e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        env->SetByteArrayRegion(b, 0, item->m_data.size(),
253e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck                                (const jbyte*)item->m_data.data());
254e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        item->m_dataCached = env->NewGlobalRef(b);
255e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        env->DeleteLocalRef(b);
256e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    }
257e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    return item->m_dataCached;
258e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck}
259e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
260e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reckstatic jobject WebHistoryGetFavicon(JNIEnv* env, jobject obj, jint ptr)
261e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck{
262e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (!ptr)
263e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        return 0;
264e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
265e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    MutexLocker locker(item->m_lock);
2664d31493c3fa47a28b2753bc5b99e2074b6a7a4dfJohn Reck    if (!item->m_faviconCached && item->m_favicon) {
267e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        jobject favicon = GraphicsJNI::createBitmap(env,
2684d31493c3fa47a28b2753bc5b99e2074b6a7a4dfJohn Reck                                                    item->m_favicon,
269e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck                                                    false, NULL);
2704d31493c3fa47a28b2753bc5b99e2074b6a7a4dfJohn Reck        item->m_favicon = 0; // Framework now owns the pointer
271e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        item->m_faviconCached = env->NewGlobalRef(favicon);
272e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        env->DeleteLocalRef(favicon);
273e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    }
274e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    return item->m_faviconCached;
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
27761e86687816f581053a96dc2686208fe3616ae40Shimeng (Simon) Wang// 6 empty strings + no document state + children count + 2 scales = 10 unsigned values
27861e86687816f581053a96dc2686208fe3616ae40Shimeng (Simon) Wang// 1 char for isTargetItem.
27961e86687816f581053a96dc2686208fe3616ae40Shimeng (Simon) Wang#define HISTORY_MIN_SIZE ((int)(sizeof(unsigned) * 10 + sizeof(char)))
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
281e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reckvoid WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& vector, WebCore::HistoryItem* item)
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!item)
284e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        return;
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Reserve a vector of chars with an initial size of HISTORY_MIN_SIZE.
287c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    vector.reserveCapacity(HISTORY_MIN_SIZE);
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Write the top-level history item and then write all the children
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // recursively.
2916dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(item->bridge(), "Why don't we have a bridge object here?");
292c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    writeItem(vector, item);
293c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    writeChildrenRecursive(vector, item);
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebHistoryItem::updateHistoryItem(WebCore::HistoryItem* item) {
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do not want to update during inflation.
298be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch    if (!m_active)
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebHistoryItem* webItem = this;
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Now we need to update the top-most WebHistoryItem based on the top-most
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // HistoryItem.
303be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch    if (m_parent) {
304be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch        webItem = m_parent.get();
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (webItem->hasOneRef()) {
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // if the parent only has one ref, it is from this WebHistoryItem.
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // This means that the matching WebCore::HistoryItem has been freed.
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // This can happen during clear().
3097d99b5804f0800191b03d83fc8f8d2886271475bSteve Block            ALOGW("Can't updateHistoryItem as the top HistoryItem is gone");
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (webItem->parent())
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            webItem = webItem->parent();
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        item = webItem->historyItem();
315fdd2ae400181744b916fcc8319e68f1cec57c981Grace Kloba        if (!item) {
316fdd2ae400181744b916fcc8319e68f1cec57c981Grace Kloba            // If a HistoryItem only exists for page cache, it is possible that
317fdd2ae400181744b916fcc8319e68f1cec57c981Grace Kloba            // the parent HistoryItem destroyed before the child HistoryItem. If
318fdd2ae400181744b916fcc8319e68f1cec57c981Grace Kloba            // it happens, skip updating.
3197d99b5804f0800191b03d83fc8f8d2886271475bSteve Block            ALOGW("Can't updateHistoryItem as the top HistoryItem is gone");
320fdd2ae400181744b916fcc8319e68f1cec57c981Grace Kloba            return;
321fdd2ae400181744b916fcc8319e68f1cec57c981Grace Kloba        }
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JNIEnv* env = JSC::Bindings::getJNIEnv();
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!env)
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
327e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    MutexLocker locker(webItem->m_lock);
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
329e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    // TODO: Figure out if we can't just use item->urlString() instead...
330d20466cbeb31c73eace8f0c4eb6c717b1e1ae540Shimeng (Simon) Wang    const WTF::String urlString = WebFrame::convertIDNToUnicode(item->url());
331e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    webItem->m_url = urlString.threadsafeCopy();
332d20466cbeb31c73eace8f0c4eb6c717b1e1ae540Shimeng (Simon) Wang    const WTF::String originalUrlString = WebFrame::convertIDNToUnicode(item->originalURL());
333e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    webItem->m_originalUrl = originalUrlString.threadsafeCopy();
33445b64f60af3cbfa8c78388e35e9b669a0c284bdcBen Murdoch    const WTF::String& titleString = item->title();
335e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    webItem->m_title = titleString.threadsafeCopy();
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Try to get the favicon from the history item. For some pages like Grand
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Prix, there are history items with anchors. If the icon fails for the
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // item, try to get the icon using the url without the ref.
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jobject favicon = NULL;
34145b64f60af3cbfa8c78388e35e9b669a0c284bdcBen Murdoch    WTF::String url = item->urlString();
3429e2ee40924101fa594b0b31d866f896154b47caaBen Murdoch    if (item->url().hasFragmentIdentifier()) {
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int refIndex = url.reverseFind('#');
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        url = url.substring(0, refIndex);
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3462f4ef9300ef5b74c660927a63057e2fcff0e1905Steve Block    // FIXME: This method should not be used from outside WebCore and will be removed.
3472f4ef9300ef5b74c660927a63057e2fcff0e1905Steve Block    // http://trac.webkit.org/changeset/81484
3482f4ef9300ef5b74c660927a63057e2fcff0e1905Steve Block    WebCore::Image* icon = WebCore::iconDatabase().synchronousIconForPageURL(url, WebCore::IntSize(16, 16));
3494d31493c3fa47a28b2753bc5b99e2074b6a7a4dfJohn Reck    delete webItem->m_favicon;
350e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    webItem->m_favicon = webcoreImageToSkBitmap(icon);
351e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (webItem->m_faviconCached) {
352e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        env->DeleteGlobalRef(webItem->m_faviconCached);
353e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        webItem->m_faviconCached = 0;
354e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    }
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
356e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    webItem->m_data.clear();
357e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    WebHistory::Flatten(env, webItem->m_data, item);
358e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (webItem->m_dataCached) {
359e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        env->DeleteGlobalRef(webItem->m_dataCached);
360e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        webItem->m_dataCached = 0;
361e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    }
362e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck}
363e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
364e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn ReckWebHistoryItem::~WebHistoryItem()
365e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck{
3664d31493c3fa47a28b2753bc5b99e2074b6a7a4dfJohn Reck    delete m_favicon;
367e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    JNIEnv* env = JSC::Bindings::getJNIEnv();
368e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (!env) {
369e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        ALOGW("Failed to get JNIEnv*! Potential memory leak!");
370e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        return;
371e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    }
372e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (m_faviconCached) {
373e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        env->DeleteGlobalRef(m_faviconCached);
374e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        m_faviconCached = 0;
375e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    }
376e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    if (m_dataCached) {
377e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        env->DeleteGlobalRef(m_dataCached);
378e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        m_dataCached = 0;
379e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    }
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void historyItemChanged(WebCore::HistoryItem* item) {
3836dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(item, "historyItemChanged called with a null item");
384be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (item->bridge())
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        item->bridge()->updateHistoryItem(item);
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item)
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3916dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(item, "newItem must take a valid HistoryItem!");
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Item already added. Should only happen when we are inflating the list.
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (item->bridge() || !list.get())
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JNIEnv* env = list.env();
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Create the bridge, make it active, and attach it to the item.
398e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    WebHistoryItem* bridge = new WebHistoryItem(item);
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bridge->setActive();
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    item->setBridge(bridge);
401e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    // Allocate a blank WebHistoryItem
402e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    jclass clazz = env->FindClass("android/webkit/WebHistoryItem");
403e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    jobject newItem = env->NewObject(clazz, gWebHistoryItem.mInit,
404e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck            reinterpret_cast<int>(bridge));
405e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    env->DeleteLocalRef(clazz);
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Update the history item which will flatten the data and call update on
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // the java item.
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bridge->updateHistoryItem(item);
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Add it to the list.
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->CallVoidMethod(list.get(), gWebBackForwardList.mAddHistoryItem, newItem);
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Delete our local reference.
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->DeleteLocalRef(newItem);
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebHistory::RemoveItem(const AutoJObject& list, int index)
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (list.get())
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        list.env()->CallVoidMethod(list.get(), gWebBackForwardList.mRemoveHistoryItem, index);
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebHistory::UpdateHistoryIndex(const AutoJObject& list, int newIndex)
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (list.get())
427730ce864fef32412598ac6b1f5e48a02f217ca25Patrick Scott        list.env()->CallVoidMethod(list.get(), gWebBackForwardList.mSetCurrentIndex, newIndex);
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
430c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brennerstatic void writeString(WTF::Vector<char>& vector, const WTF::String& str)
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned strLen = str.length();
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Only do work if the string has data.
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (strLen) {
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Determine how much to grow the vector. Use the worst case for utf8 to
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // avoid reading the string twice. Add sizeof(unsigned) to hold the
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // string length in utf8.
438c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        unsigned vectorLen = vector.size() + sizeof(unsigned);
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned length = (strLen << 2) + vectorLen;
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Grow the vector. This will change the value of v.size() but we
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // remember the original size above.
442c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        vector.grow(length);
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Grab the position to write to.
444c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        char* data = vector.begin() + vectorLen;
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Write the actual string
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int l = SkUTF16_ToUTF8(str.characters(), strLen, data);
447c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        ALOGV("Writing string          %d %.*s", l, l, data);
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Go back and write the utf8 length. Subtract sizeof(unsigned) from
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // data to get the position to write the length.
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        memcpy(data - sizeof(unsigned), (char*)&l, sizeof(unsigned));
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Shrink the internal state of the vector so we match what was
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // actually written.
453c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        vector.shrink(vectorLen + l);
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else
455c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        vector.append((char*)&strLen, sizeof(unsigned));
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brennerstatic void writeItem(WTF::Vector<char>& vector, WebCore::HistoryItem* item)
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Original url
461c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    writeString(vector, item->originalURLString());
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Url
464c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    writeString(vector, item->urlString());
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Title
467c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    writeString(vector, item->title());
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Form content type
470c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    writeString(vector, item->formContentType());
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Form data
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const WebCore::FormData* formData = item->formData();
474ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba    if (formData) {
475c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        writeString(vector, formData->flattenToString());
476ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba        // save the identifier as it is not included in the flatten data
477ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba        int64_t id = formData->identifier();
478c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        vector.append((char*)&id, sizeof(int64_t));
479ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba    } else
480c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        writeString(vector, WTF::String()); // Empty constructor does not allocate a buffer.
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Target
483c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    writeString(vector, item->target());
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
485be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch    AndroidWebHistoryBridge* bridge = item->bridge();
4866dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(bridge, "We should have a bridge here!");
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Screen scale
488c4683829d0d4932156a97ce14ea15deed71bf21dShimeng (Simon) Wang    const float scale = bridge->scale();
489c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOGV("Writing scale           %f", scale);
490c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    vector.append((char*)&scale, sizeof(float));
491c4683829d0d4932156a97ce14ea15deed71bf21dShimeng (Simon) Wang    const float textWrapScale = bridge->textWrapScale();
492c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOGV("Writing text wrap scale %f", textWrapScale);
493c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    vector.append((char*)&textWrapScale, sizeof(float));
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
495bfc0ebd2ace64845c11b40ce5dae09347ce0020dShimeng (Simon) Wang    // Scroll position.
496bfc0ebd2ace64845c11b40ce5dae09347ce0020dShimeng (Simon) Wang    const int scrollX = item->scrollPoint().x();
497c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    vector.append((char*)&scrollX, sizeof(int));
498bfc0ebd2ace64845c11b40ce5dae09347ce0020dShimeng (Simon) Wang    const int scrollY = item->scrollPoint().y();
499c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    vector.append((char*)&scrollY, sizeof(int));
500bfc0ebd2ace64845c11b40ce5dae09347ce0020dShimeng (Simon) Wang
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Document state
50245b64f60af3cbfa8c78388e35e9b669a0c284bdcBen Murdoch    const WTF::Vector<WTF::String>& docState = item->documentState();
50345b64f60af3cbfa8c78388e35e9b669a0c284bdcBen Murdoch    WTF::Vector<WTF::String>::const_iterator end = docState.end();
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned stateSize = docState.size();
505c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOGV("Writing docState        %d", stateSize);
506c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    vector.append((char*)&stateSize, sizeof(unsigned));
50745b64f60af3cbfa8c78388e35e9b669a0c284bdcBen Murdoch    for (WTF::Vector<WTF::String>::const_iterator i = docState.begin(); i != end; ++i) {
508c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        writeString(vector, *i);
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Is target item
512c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOGV("Writing isTargetItem    %d", item->isTargetItem());
513c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    vector.append((char)item->isTargetItem());
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Children count
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned childCount = item->children().size();
517c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOGV("Writing childCount      %d", childCount);
518c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    vector.append((char*)&childCount, sizeof(unsigned));
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
521c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brennerstatic void writeChildrenRecursive(WTF::Vector<char>& vector, WebCore::HistoryItem* parent)
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const WebCore::HistoryItemVector& children = parent->children();
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::HistoryItemVector::const_iterator end = children.end();
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (WebCore::HistoryItemVector::const_iterator i = children.begin(); i != end; ++i) {
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WebCore::HistoryItem* item = (*i).get();
5276dd76b804786ec760bb04b137a6bf017064226dcSteve Block        ALOG_ASSERT(parent->bridge(),
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                "The parent item should have a bridge object!");
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!item->bridge()) {
530be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch            WebHistoryItem* bridge = new WebHistoryItem(static_cast<WebHistoryItem*>(parent->bridge()));
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            item->setBridge(bridge);
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            bridge->setActive();
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // The only time this item's parent may not be the same as the
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // parent's bridge is during history close. In that case, the
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // parent must not have a parent bridge.
537be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch            WebHistoryItem* bridge = static_cast<WebHistoryItem*>(item->bridge());
538be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch            WebHistoryItem* parentBridge = static_cast<WebHistoryItem*>(parent->bridge());
5396dd76b804786ec760bb04b137a6bf017064226dcSteve Block            ALOG_ASSERT(parentBridge->parent() == 0 ||
540be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch                    bridge->parent() == parentBridge,
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    "Somehow this item has an incorrect parent");
542be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch            bridge->setParent(parentBridge);
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
544c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        writeItem(vector, item);
545c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner        writeChildrenRecursive(vector, item);
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
54908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readUnsigned(const char*& data, const char* end, unsigned& result, const char* dbgLabel = 0);
55008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readInt(const char*& data, const char* end, int& result, const char* dbgLabel = 0);
55108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readInt64(const char*& data, const char* end, int64_t& result, const char* dbgLabel = 0);
55208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readFloat(const char*& data, const char* end, float& result, const char* dbgLabel = 0);
55308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readBool(const char*& data, const char* end, bool& result, const char* dbgLabel = 0);
55408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readString(const char*& data, const char* end, String& result, const char* dbgLabel = 0);
55508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
55608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readUnsigned(const char*& data, const char* end, unsigned& result, const char* dbgLabel)
55708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner{
55808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // Check if we have enough data left to continue.
55908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(unsigned))) {
560541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("\tNot enough data to read unsigned; tag=\"%s\" end=%p data=%p",
561541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              dbgLabel ? dbgLabel : "<no tag>", end, data);
56208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
56308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
56408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
56508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    memcpy(&result, data, sizeof(unsigned));
56608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    data += sizeof(unsigned);
56708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (dbgLabel)
56808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        ALOGV("Reading %-16s %u", dbgLabel, result);
56908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    return true;
57008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner}
57108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
57208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readInt(const char*& data, const char* end, int& result, const char* dbgLabel)
57308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner{
57408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // Check if we have enough data left to continue.
57508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(int))) {
576541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("Not enough data to read int; tag=\"%s\" end=%p data=%p",
577541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              dbgLabel ? dbgLabel : "<no tag>", end, data);
57808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
57908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
58008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
58108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    memcpy(&result, data, sizeof(int));
58208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    data += sizeof(int);
58308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (dbgLabel)
58408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        ALOGV("Reading %-16s %d", dbgLabel, result);
58508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    return true;
58608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner}
58708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
58808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readInt64(const char*& data, const char* end, int64_t& result, const char* dbgLabel)
58908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner{
59008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // Check if we have enough data left to continue.
59108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(int64_t))) {
592541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("Not enough data to read int64_t; tag=\"%s\" end=%p data=%p",
593541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              dbgLabel ? dbgLabel : "<no tag>", end, data);
59408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
59508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
59608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
59708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    memcpy(&result, data, sizeof(int64_t));
59808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    data += sizeof(int64_t);
59908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (dbgLabel)
60008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        ALOGV("Reading %-16s %ll", dbgLabel, result);
60108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    return true;
60208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner}
60308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
60408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readFloat(const char*& data, const char* end, float& result, const char* dbgLabel)
60508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner{
60608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // Check if we have enough data left to continue.
60708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(float))) {
608541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("Not enough data to read float; tag=\"%s\" end=%p data=%p",
609541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              dbgLabel ? dbgLabel : "<no tag>", end, data);
61008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
61108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
61208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
61308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    memcpy(&result, data, sizeof(float));
61408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    data += sizeof(float);
61508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (dbgLabel)
61608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        ALOGV("Reading %-16s %f", dbgLabel, result);
61708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    return true;
61808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner}
61908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
62008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner// Note that the return value indicates success or failure, while the result
62108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner// parameter indicates the read value of the bool
62208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readBool(const char*& data, const char* end, bool& result, const char* dbgLabel)
62308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner{
62408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // Check if we have enough data left to continue.
62508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(char))) {
626541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("Not enough data to read bool; tag=\"%s\" end=%p data=%p",
627541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              dbgLabel ? dbgLabel : "<no tag>", end, data);
62808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
62908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
63008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
63108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    char c;
63208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    memcpy(&c, data, sizeof(char));
63308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    data += sizeof(char);
63408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (dbgLabel)
63508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        ALOGV("Reading %-16s %d", dbgLabel, c);
63608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    result = c;
63708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
63808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // Valid bool results are 0 or 1
63908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if ((c != 0) && (c != 1)) {
640541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("Invalid value for bool; tag=\"%s\" end=%p data=%p c=%u",
641541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              dbgLabel ? dbgLabel : "<no tag>", end, data, c);
64208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
64308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
64408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
64508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    return true;
64608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner}
64708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
64808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brennerbool readString(const char*& data, const char* end, String& result, const char* dbgLabel)
64908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner{
65008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    unsigned stringLength;
65108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (!readUnsigned(data, end, stringLength)) {
652541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("Not enough data to read string length; tag=\"%s\" end=%p data=%p",
653541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              dbgLabel ? dbgLabel : "<no tag>", end, data);
65408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
65508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
65608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
65708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (dbgLabel)
65808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        ALOGV("Reading %-16s %d %.*s", dbgLabel, stringLength, stringLength, data);
65908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
66008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // If length was 0, there will be no string content, but still return true
66108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (!stringLength) {
66208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        result = String();
66308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return true;
66408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
66508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
66608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if ((end < data) || ((unsigned)(end - data) < stringLength)) {
667541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("Not enough data to read content; tag=\"%s\" end=%p data=%p stringLength=%u",
668541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              dbgLabel ? dbgLabel : "<no tag>", end, data, stringLength);
66908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
67008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
67108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
672541839a11103a72d486edaab8a5c9e9499554511Russell Brenner    const unsigned MAX_REASONABLE_STRING_LENGTH = 10000;
673541839a11103a72d486edaab8a5c9e9499554511Russell Brenner    if (stringLength > MAX_REASONABLE_STRING_LENGTH) {
674541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("String length is suspiciously large (>%d); tag=\"%s\" end=%p data=%p stringLength=%u",
675541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              MAX_REASONABLE_STRING_LENGTH, dbgLabel ? dbgLabel : "<no tag>",
676541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              end, data, stringLength);
677541839a11103a72d486edaab8a5c9e9499554511Russell Brenner    }
678541839a11103a72d486edaab8a5c9e9499554511Russell Brenner
679859c01f9680c58ddff5938862087b41478acd0a0Russell Brenner    bool decodeFailed = false;
68008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    static const WebCore::TextEncoding& encoding = WebCore::UTF8Encoding();
68108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    result = encoding.decode(data, stringLength, true, decodeFailed);
68208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (decodeFailed) {
683541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("Decode failed, tag=\"%s\" end=%p data=%p stringLength=%u content=\"%s\"",
684541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              dbgLabel ? dbgLabel : "<no tag>", end, data, stringLength,
685541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              result.utf8().data());
686859c01f9680c58ddff5938862087b41478acd0a0Russell Brenner        return false;
68708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
68808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
689541839a11103a72d486edaab8a5c9e9499554511Russell Brenner    if (stringLength > MAX_REASONABLE_STRING_LENGTH) {
690541839a11103a72d486edaab8a5c9e9499554511Russell Brenner        ALOGW("\tdecodeFailed=%d (flag is ignored) content=\"%s\"",
691541839a11103a72d486edaab8a5c9e9499554511Russell Brenner              decodeFailed, result.utf8().data());
692541839a11103a72d486edaab8a5c9e9499554511Russell Brenner    }
693541839a11103a72d486edaab8a5c9e9499554511Russell Brenner
69408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    data += stringLength;
69508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    return true;
69608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner}
69708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
698c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brennerstatic bool readItemRecursive(WebCore::HistoryItem* newItem,
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const char** pData, int length)
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
70108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (!pData || length < HISTORY_MIN_SIZE) {
70208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        ALOGW("readItemRecursive() bad params; pData=%p length=%d", pData, length);
7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
70408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    }
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* data = *pData;
7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* end = data + length;
70808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    String content;
7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the original url
71108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (readString(data, end, content, "Original url"))
71208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        newItem->setOriginalURLString(content);
71308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    else
7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the url
71708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (readString(data, end, content, "Url"))
71808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        newItem->setURLString(content);
71908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    else
7208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the title
72308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (readString(data, end, content, "Title"))
72408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        newItem->setTitle(content);
72508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    else
7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Generate a new ResourceRequest object for populating form information.
72908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // Read the form content type
73045b64f60af3cbfa8c78388e35e9b669a0c284bdcBen Murdoch    WTF::String formContentType;
73108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (!readString(data, end, formContentType, "Content type"))
73208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
73408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // Read the form data size
73508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    unsigned formDataSize;
73608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (!readUnsigned(data, end, formDataSize, "Form data size"))
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the form data
74008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    WTF::RefPtr<WebCore::FormData> formData;
74108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (formDataSize) {
74208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        ALOGV("Reading Form data       %d %.*s", formDataSize, formDataSize, data);
74308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        if ((end < data) || ((size_t)(end - data) < formDataSize)) {
74408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner            ALOGW("\tNot enough data to read form data; returning");
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
746ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba        }
74708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        formData = WebCore::FormData::create(data, formDataSize);
74808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        data += formDataSize;
74908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        // Read the identifier
75008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        int64_t id;
75108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        if (!readInt64(data, end, id, "Form id"))
75208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner            return false;
75308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        if (id)
75408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner            formData->setIdentifier(id);
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Set up the form info
7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (formData != NULL) {
7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WebCore::ResourceRequest r;
7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        r.setHTTPMethod("POST");
7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        r.setHTTPContentType(formContentType);
7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        r.setHTTPBody(formData);
7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        newItem->setFormInfoFromRequest(r);
7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the target
76708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (readString(data, end, content, "Target"))
76808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        newItem->setTarget(content);
76908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    else
7708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
772be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch    AndroidWebHistoryBridge* bridge = newItem->bridge();
7736dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(bridge, "There should be a bridge object during inflate");
77408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner
7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the screen scale
77608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    float fValue;
77708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (readFloat(data, end, fValue, "Screen scale"))
77808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        bridge->setScale(fValue);
77908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    else
78008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
78161e86687816f581053a96dc2686208fe3616ae40Shimeng (Simon) Wang
78208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    // Read the text wrap scale
78308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (readFloat(data, end, fValue, "Text wrap scale"))
78408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        bridge->setTextWrapScale(fValue);
78508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    else
7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
788bfc0ebd2ace64845c11b40ce5dae09347ce0020dShimeng (Simon) Wang    // Read scroll position.
78908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    int scrollX;
79008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (!readInt(data, end, scrollX, "Scroll pos x"))
79108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
79208767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    int scrollY;
79308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (!readInt(data, end, scrollY, "Scroll pos y"))
794bfc0ebd2ace64845c11b40ce5dae09347ce0020dShimeng (Simon) Wang        return false;
79508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    newItem->setScrollPoint(IntPoint(scrollX, scrollY));
796bfc0ebd2ace64845c11b40ce5dae09347ce0020dShimeng (Simon) Wang
7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the document state
79808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    unsigned docStateCount;
79908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (!readUnsigned(data, end, docStateCount, "Doc state count"))
80008767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
80108767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (docStateCount) {
8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Create a new vector and reserve enough space for the document state.
80345b64f60af3cbfa8c78388e35e9b669a0c284bdcBen Murdoch        WTF::Vector<WTF::String> docState;
80408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        docState.reserveCapacity(docStateCount);
80508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        while (docStateCount--) {
80608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner            // Read a document state string
80708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner            if (readString(data, end, content, "Document state"))
80808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner                docState.append(content);
8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        newItem->setDocumentState(docState);
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read is target item
81608767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    bool c;
81708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (readBool(data, end, c, "Target item"))
81808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        newItem->setIsTargetItem(c);
81908767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    else
8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the child count
82308767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    unsigned count;
82408767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (!readUnsigned(data, end, count, "Child count"))
82508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        return false;
8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *pData = data;
82708767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner    if (count) {
82808767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner        while (count--) {
8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // No need to check the length each time because read_item_recursive
8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // will return null if there isn't enough data left to parse.
8313577745d3cfbfe2b7ebb3cddb1abda7026a61ac5Russell Brenner            WTF::RefPtr<WebCore::HistoryItem> child = WebCore::HistoryItem::create();
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Set a bridge that will not call into java.
833be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch            child->setBridge(new WebHistoryItem(static_cast<WebHistoryItem*>(bridge)));
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Read the child item.
83508767a79b9fae453edaed3c64afe1f52ba64b195Russell Brenner            if (!readItemRecursive(child.get(), pData, end - data))
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            child->bridge()->setActive();
8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newItem->addChildItem(child);
8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// On arm, this test will cause memory corruption since converting char* will
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// byte align the result and this test does not use memset (it probably
8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// should).
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// On the simulator, using HistoryItem will invoke the IconDatabase which will
8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// initialize the main thread. Since this is invoked by the Zygote process, the
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// main thread will be incorrect and an assert will fire later.
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// In conclusion, define UNIT_TEST only if you know what you are doing.
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef UNIT_TEST
852c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brennerstatic void unitTest()
8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
854a09e7cf49f43950a799f936bf42a9912d696547bSteve Block    ALOGD("Entering history unit test!");
8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* test1 = new char[0];
8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WTF::RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create();
8578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::HistoryItem* testItem = item.get();
858be33b78f63b17f1b6f5a36a503d797d5f9b941eeBen Murdoch    testItem->setBridge(new WebHistoryItem(0));
859c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &test1, 0), "0 length array should fail!");
8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test1;
8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* test2 = new char[2];
862c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &test2, 2), "Small array should fail!");
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test2;
864c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, NULL, HISTORY_MIN_SIZE), "Null data should fail!");
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Original Url
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char* test3 = new char[HISTORY_MIN_SIZE];
8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* ptr = (const char*)test3;
8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)test3 = 4000;
870c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length originalUrl should fail!");
8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Url
8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int offset = 4;
8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
876c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length url should fail!");
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Title
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
882c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length title should fail!");
8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Form content type
8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
888c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length contentType should fail!");
8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Form data
8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
894c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length form data should fail!");
8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Target
8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
900c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length target should fail!");
9019cff7e8839f4cd5caf01f005647176461f329a8dRussell Brenner    offset += 4; // Screen scale
9029cff7e8839f4cd5caf01f005647176461f329a8dRussell Brenner    offset += 4; // Text wrap scale
9039cff7e8839f4cd5caf01f005647176461f329a8dRussell Brenner    offset += 4; // Scroll pos x
9049cff7e8839f4cd5caf01f005647176461f329a8dRussell Brenner    offset += 4; // Scroll pos y
9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Document state
9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
910c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length document state should fail!");
9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Is target item
9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 1;
9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(char*)(test3 + offset) = '!';
916c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "IsTargetItem should fail with ! as the value!");
9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Child count
9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
922c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 kids should fail!");
9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Test document state
9249cff7e8839f4cd5caf01f005647176461f329a8dRussell Brenner    offset = 40;
9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test3;
9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    test3 = new char[HISTORY_MIN_SIZE + sizeof(unsigned)];
9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE + sizeof(unsigned));
9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 1;
9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset + 4) = 20;
931c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE + sizeof(unsigned)), "1 20 length document state string should fail!");
9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test3;
9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    test3 = new char[HISTORY_MIN_SIZE + 2 * sizeof(unsigned)];
9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE + 2 * sizeof(unsigned));
9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 2;
9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset + 4) = 0;
9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset + 8) = 20;
939c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE + 2 * sizeof(unsigned) ), "2 20 length document state string should fail!");
9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test3;
9419cff7e8839f4cd5caf01f005647176461f329a8dRussell Brenner    ALOGD("Leaving history unit test!");
9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project//---------------------------------------------------------
9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// JNI registration
9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project//---------------------------------------------------------
9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic JNINativeMethod gWebBackForwardListMethods[] = {
9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    { "nativeClose", "(I)V",
9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        (void*) WebHistoryClose },
9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    { "restoreIndex", "(II)V",
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        (void*) WebHistoryRestoreIndex }
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic JNINativeMethod gWebHistoryItemMethods[] = {
956e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    { "inflate", "(I[B)I",
957e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        (void*) WebHistoryInflate },
958e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    { "nativeRef", "(I)V",
959e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        (void*) WebHistoryRef },
960e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    { "nativeUnref", "(I)V",
961e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        (void*) WebHistoryUnref },
962e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    { "nativeGetTitle", "(I)Ljava/lang/String;",
963e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        (void*) WebHistoryGetTitle },
964e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    { "nativeGetUrl", "(I)Ljava/lang/String;",
965e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        (void*) WebHistoryGetUrl },
966e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    { "nativeGetOriginalUrl", "(I)Ljava/lang/String;",
967e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        (void*) WebHistoryGetOriginalUrl },
968e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    { "nativeGetFlattenedData", "(I)[B",
969e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        (void*) WebHistoryGetFlattenedData },
970e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    { "nativeGetFavicon", "(I)Landroid/graphics/Bitmap;",
971e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck        (void*) WebHistoryGetFavicon },
9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
974b92850e0391d674b9c4826b66105aaa3dd3eef96Steve Blockint registerWebHistory(JNIEnv* env)
9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Get notified of all changes to history items.
9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::notifyHistoryItemChanged = historyItemChanged;
9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef UNIT_TEST
979c8c13e36333629a06a196f84e75f2cc8ae5df24eRussell Brenner    unitTest();
9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Find WebHistoryItem, its constructor, and the update method.
9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jclass clazz = env->FindClass("android/webkit/WebHistoryItem");
9836dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebHistoryItem");
984e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck    gWebHistoryItem.mInit = env->GetMethodID(clazz, "<init>", "(I)V");
9856dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(gWebHistoryItem.mInit, "Could not find WebHistoryItem constructor");
986e38a6c283211dcfd3b1fb390e4c108a86481dd8aJohn Reck
987bf3f67c4fcfd68df256e5c001c67969997a63e28Steve Block    env->DeleteLocalRef(clazz);
9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
989730ce864fef32412598ac6b1f5e48a02f217ca25Patrick Scott    // Find the WebBackForwardList object and method.
9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    clazz = env->FindClass("android/webkit/WebBackForwardList");
9916dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebBackForwardList");
9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gWebBackForwardList.mAddHistoryItem = env->GetMethodID(clazz, "addHistoryItem",
9938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            "(Landroid/webkit/WebHistoryItem;)V");
9946dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(gWebBackForwardList.mAddHistoryItem, "Could not find method addHistoryItem");
9958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gWebBackForwardList.mRemoveHistoryItem = env->GetMethodID(clazz, "removeHistoryItem",
9968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            "(I)V");
9976dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(gWebBackForwardList.mRemoveHistoryItem, "Could not find method removeHistoryItem");
998730ce864fef32412598ac6b1f5e48a02f217ca25Patrick Scott    gWebBackForwardList.mSetCurrentIndex = env->GetMethodID(clazz, "setCurrentIndex", "(I)V");
9996dd76b804786ec760bb04b137a6bf017064226dcSteve Block    ALOG_ASSERT(gWebBackForwardList.mSetCurrentIndex, "Could not find method setCurrentIndex");
1000bf3f67c4fcfd68df256e5c001c67969997a63e28Steve Block    env->DeleteLocalRef(clazz);
10018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int result = jniRegisterNativeMethods(env, "android/webkit/WebBackForwardList",
10038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gWebBackForwardListMethods, NELEM(gWebBackForwardListMethods));
10048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (result < 0) ? result : jniRegisterNativeMethods(env, "android/webkit/WebHistoryItem",
10058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gWebHistoryItemMethods, NELEM(gWebHistoryItemMethods));
10068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} /* namespace android */
1009